前言:vue3.0要用Proxy來實(shí)現(xiàn)雙向綁定,因此先來嘗試一下實(shí)現(xiàn)方法。
1 Object.defineProperty 實(shí)現(xiàn)
原來vue2的實(shí)現(xiàn)使用Object.defineProperty,監(jiān)聽set,但對(duì)于數(shù)組直接下標(biāo)給數(shù)組設(shè)置值監(jiān)聽不了。
function observe(data) { if (!data || typeof data !== 'object') { return; } // 取出所有屬性遍歷 Object.keys(data).forEach(function(key) { defineReactive(data, key, data[key]); }); }; function defineReactive(data, key, val) { observe(val); // 監(jiān)聽子屬性 Object.defineProperty(data, key, { enumerable: true, // 可枚舉 configurable: false, // 不能再重寫defineProperty get: function() { return val; }, set: function(newVal) { console.log('-------通知訂閱者--------') val = newVal; } }); }
2 使用Proxy實(shí)現(xiàn)
使用Proxy實(shí)現(xiàn)原理主要是new一個(gè)Proxy對(duì)象,代理你的data值,需要注意的一點(diǎn)是,對(duì)于數(shù)組的方法操作來說,會(huì)產(chǎn)生兩次賦值操作,一次是添加值,一次是改變他的length值,而對(duì)于Object.defineProperty監(jiān)聽不到的數(shù)組下標(biāo)給數(shù)組設(shè)置值,Proxy是可以監(jiān)聽到的。
function observe(data) { if (!data || typeof data !== 'object') { return; } // 取出所有屬性遍歷 Object.keys(data).forEach(function(_k) { // Proxy不允許綁定在非對(duì)象上 if (data[_k] && typeof data[_k] === 'object') { data[_k] = defineReactive(data[_k]); } }); } function defineReactive(data) { return new Proxy(data, { set(target, key, value, proxy) { // 進(jìn)行數(shù)組操作時(shí),會(huì)進(jìn)行兩次set 一次數(shù)據(jù)改變,一次length改變,兩次改變data的值是不變,因此不應(yīng)該多分發(fā)一次消息 if ( Object.prototype.toString.call(data) === "[object Array]" && key === "length" ) { Reflect.set(target, key, value, proxy); return true; } observe(data); Reflect.set(target, key, value, proxy); console.log('-------通知訂閱者--------') return true; } });
聲明:本網(wǎng)頁內(nèi)容旨在傳播知識(shí),若有侵權(quán)等問題請(qǐng)及時(shí)與本網(wǎng)聯(lián)系,我們將在第一時(shí)間刪除處理。TEL:177 7030 7066 E-MAIL:11247931@qq.com