vue數(shù)據(jù)響應(yīng)式原理重寫(xiě)函數(shù)實(shí)現(xiàn)數(shù)組響應(yīng)式監(jiān)聽(tīng)
output.js代碼:
import { observe } from "./dataResp" const output = () => { var obj = { data: { data: { map: { dom: { isgin: true } }, arg: 13 }, name: "小貓貓" }, bool: [1,2,3,4] }; observe(obj); obj.bool.push(7); document.getElementById("text").innerHTML = obj.data.name; } export default output
運(yùn)行結(jié)果如下
很明顯 我們數(shù)組并捕獲不到 push方法 除了 push 很多數(shù)組方法都捕獲不到
首先 我們來(lái)看幾個(gè)方法 分別是
這幾個(gè)方法執(zhí)行 說(shuō)明 當(dāng)前數(shù)組被改寫(xiě)了內(nèi)容
那么 我們可以去改寫(xiě)這七個(gè)方法 我們?cè)诎咐?src目錄下創(chuàng)建 Arrays.js 然后 大家先要知道 這些方法被定義在哪里? Array.prototype Array是數(shù)組類(lèi)型的一個(gè)類(lèi)對(duì)象 這些方法就定義在Array的原型鏈上 所以 大家才能通過(guò) 數(shù)組.這些方法 去調(diào)用他們 而我們要做的就是 重寫(xiě)這些方法 要做的就是 調(diào)用原來(lái)的方法 然后 在后面再去做自己需要做的響應(yīng)式的事情
我們先在src下創(chuàng)建一個(gè)def.js 然后將之前寫(xiě)在dataResp.js中的def放進(jìn)def.js來(lái)
export const def = function(obj,key,value,enumerable) { Object.defineProperty(obj,key,{ value, enumerable, //true 設(shè)為可寫(xiě) writable: true, //true 設(shè)為可被刪除 configurable: true }); }
然后 將dataResp.js中的def方法干掉 然后 dataResp.js引入一下def.js的 def方法
import {<!--{C}%3C!%2D%2D%20%2D%2D%3E--> def } from './def.js';
這個(gè)是我之前沒(méi)想清楚 抱歉
然后 我們?cè)贏rrays.js中編寫(xiě)代碼如下
import { def } from './def.js'; const arrayPrototype = Array.prototype; export const arrayMethods = Object.create(arrayPrototype); const redefineArrayMethod = [ 'push', 'pop', 'shift', 'unshift', 'splice', 'sort', 'reverse' ] redefineArrayMethod.forEach(item =>{ const backupFunction = arrayPrototype[item]; def(arrayMethods,item,function(){ backupFunction.apply(this, arguments); console.log('數(shù)組執(zhí)行了',item,'操作,值被修改為',this); },false); })
這里 我們先定義了redefineArrayMethod變量 他的值是一個(gè)數(shù)組 對(duì)應(yīng)下面每一個(gè)字符串下標(biāo) 都是這些改變數(shù)組結(jié)構(gòu)的函數(shù)關(guān)鍵字
然后定義 arrayPrototype 存一下Array的 原型鏈 prototype 因?yàn)?這些函數(shù)就在上面
然后 創(chuàng)建arrayMethods 記錄創(chuàng)建數(shù)組 并將arrayPrototype
最后 循環(huán)redefineArrayMethod 對(duì)應(yīng)每一次下標(biāo)循環(huán) 拿到都是一個(gè)數(shù)組方法關(guān)鍵字 第一次拿到’push’ 第二次’pop’
然后 我們的響應(yīng)式代碼就可以寫(xiě)在這里 首先 我們先
const backupFunction = arrayPrototype[item];
備份一下原來(lái)的方法 因?yàn)?你別重寫(xiě)之后 方法原有的邏輯沒(méi)有了啊 是不是
你別說(shuō) push我監(jiān)聽(tīng)一下 寫(xiě)完 push都加不進(jìn)去東西了 那響應(yīng)個(gè)啥 這BUG了啊
然后 我們調(diào)用def
第一個(gè)參數(shù)是 arrayMethods 就是被創(chuàng)建的對(duì)象
第二個(gè) 這里傳的是 當(dāng)前循環(huán)的內(nèi)容 就是方法名數(shù)組下標(biāo) 看著是第幾次循環(huán) 第一次 push 第二次 pop 第三次 shift 依次類(lèi)推
第四個(gè)參數(shù) 不用說(shuō) 這東西你們肯定不希望他參與遍歷吧 果斷false 至于第三個(gè) 是他的值 我們要改寫(xiě)這個(gè)函數(shù)啊 就寫(xiě)了這個(gè)函數(shù)新的內(nèi)容
backupFunction.apply(this, arguments);
先把我們備份的之前的函數(shù)內(nèi)容執(zhí)行了 就是 比如 push 我們先用執(zhí)行參數(shù)幫他把push應(yīng)該有的增加下標(biāo)的邏輯執(zhí)行了 this不用說(shuō) 肯定要的 當(dāng)前對(duì)象 然后arguments代表我們當(dāng)前函數(shù)拿到的所有參數(shù) 全部給了backupFunction.apply當(dāng)參數(shù) 就是保證參數(shù)不要少了
然后下面的代碼 我們就捕獲被改變的這個(gè)事情
然后 我們改寫(xiě) dataResp.js中的Observer類(lèi)代碼如下
class Observer{ constructor(value) { //相當(dāng)于 給拿到的對(duì)象 其中的__ob__綁定 值為thsi,在類(lèi)中用this 表示取實(shí)例本身給__ob__賦值 最后一個(gè)enumerable為false 表示屬性不參與for遍歷 def(value,'__ob__',this,false); if(Array.isArray(value)){ Object.setPrototypeOf(value, arrayMethods); } this.walk(value); } walk(value) { for(let key in value){ defineReactive(value,key); } } }
就是 監(jiān)聽(tīng)到 如果是數(shù)字類(lèi)型 調(diào)用一下 Object.setPrototypeOf 監(jiān)聽(tīng)
然后 我們?cè)俅芜\(yùn)行代碼
可以看到 我們重寫(xiě)的方法 就起效了 push被成功捕獲 并輸出了語(yǔ)句
到此這篇關(guān)于vue數(shù)據(jù)響應(yīng)式原理重寫(xiě)函數(shù)實(shí)現(xiàn)數(shù)組響應(yīng)式監(jiān)聽(tīng)的文章就介紹到這了,更多相關(guān)vue重寫(xiě)函數(shù)實(shí)現(xiàn)數(shù)組響應(yīng)式監(jiān)聽(tīng)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
springboot?@Async?注解如何實(shí)現(xiàn)方法異步
這篇文章主要介紹了springboot?@Async?注解如何實(shí)現(xiàn)方法異步,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-11-11使用SpringMVC響應(yīng)json格式返回的結(jié)果類(lèi)型
這篇文章主要介紹了使用SpringMVC響應(yīng)json格式返回的結(jié)果類(lèi)型,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-07-07Java并發(fā)編程之LongAdder執(zhí)行情況解析
這篇文章主要為大家介紹了Java并發(fā)編程之LongAdder執(zhí)行情況解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-04-04Java畢業(yè)設(shè)計(jì)實(shí)戰(zhàn)之養(yǎng)老院管理系統(tǒng)的實(shí)現(xiàn)
讀萬(wàn)卷書(shū)不如行萬(wàn)里路,只學(xué)書(shū)上的理論是遠(yuǎn)遠(yuǎn)不夠的,只有在實(shí)戰(zhàn)中才能獲得能力的提升,本篇文章手把手帶你用java+SSM+JSP+Easyui+maven+mysql實(shí)現(xiàn)一個(gè)養(yǎng)老院管理系統(tǒng),大家可以在過(guò)程中查缺補(bǔ)漏,提升水平2022-03-03Spring Boot與Kotlin定時(shí)任務(wù)的示例(Scheduling Tasks)
這篇文章主要介紹了Spring Boot與Kotlin定時(shí)任務(wù)的示例(Scheduling Tasks),小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2018-03-03mybatis動(dòng)態(tài)sql之新增與更新方式
這篇文章主要介紹了mybatis動(dòng)態(tài)sql之新增與更新方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-07-07spring-redis-session 自定義 key 和過(guò)期時(shí)間
這篇文章主要介紹了spring-redis-session 自定義 key 和過(guò)期時(shí)間,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-12-12