這篇文章給大家分享的是有關(guān)vue-next響應(yīng)式原理的示例分析的內(nèi)容。小編覺得挺實用的,因此分享給大家做個參考,一起跟隨小編過來看看吧。

預(yù)備知識
無論是閱讀這篇文章,還是閱讀 vue-next 響應(yīng)式模塊的源碼,首先有兩個知識點是必備的:
Proxy:es6 中新的代理內(nèi)建工具類
Reflect:es6 中新的反射工具類
由于篇幅有限,這里也不詳細(xì)贅述這兩個類的用途與使用方法了,推薦三篇我認(rèn)為不錯的文章,僅供參考:
ES6 Proxies in Depth
ES6 Proxy Traps in Depth
ES6 Reflection in Depth
接口
對于 vue-next 響應(yīng)式系統(tǒng)的 RFC,可以參考這里。雖然距離現(xiàn)在有一段時間了,但是通過閱讀源碼,可以發(fā)現(xiàn)一些影子。
我們大體要實現(xiàn)的效果如下面的代碼所示:
// 實現(xiàn)兩個方法 reactive 和 effect
const state = reactive({
count: 0
})
effect(() => {
console.log('count: ', state.count)
})
state.count++ // 輸入 count: 1可以發(fā)現(xiàn)我們熟悉的依賴收集階段(同時也是觀察者模式的訂閱過程),是在 effect 中進(jìn)行的,依賴收集的準(zhǔn)備工作(即數(shù)據(jù)劫持邏輯),是在 reactive 中進(jìn)行的,而數(shù)據(jù)變化的觸發(fā)響應(yīng)的邏輯在后面的 state.count++ 代碼執(zhí)行時進(jìn)行(同時也是觀察者模式的發(fā)布過程),之后便會執(zhí)行之前傳入 effect 內(nèi)部的回調(diào)函數(shù)并輸入 count: 1。
類型與公共變量
由于 vue-next 用 ts 進(jìn)行了重寫,這里我也使用 ts 來實現(xiàn)這個極簡版本的響應(yīng)式系統(tǒng)。主要涉及到的類型和公共變量如下:
type Effect = Function; type EffectMap = Map<string, Effect[]>; let currentEffect: Effect; const effectMap: EffectMap = new Map();
currentEffect:用來儲存當(dāng)前正在收集依賴的 effect
effectMap:代表目標(biāo)對象每個 key 所對應(yīng)的依賴于它的 effect 數(shù)組,也可以把它理解為觀察者模式中的訂閱者字典
利用 Proxy 實現(xiàn)數(shù)據(jù)劫持
在之前的版本中,vue 利用 Object.defineProperty 中的 setter 和 getter 來對數(shù)據(jù)對象進(jìn)行劫持,vue-next 則通過 Proxy。眾所周知,Object.defineProperty 所實現(xiàn)的數(shù)據(jù)劫持是有一定限制的,而 Proxy 就會強大很多。
首先,我們在腦后中,設(shè)想一下如何使用 Proxy 來實現(xiàn)數(shù)據(jù)劫持呢?很簡單,大體結(jié)構(gòu)如下所示:
export function reactive(obj) {
const proxied = new Proxy(obj, handlers);
return proxied;
}這里的 handlers 是聲明如何處理各個 trap 的邏輯,比如:
const handlers = {
get: function(target, key, receiver) {
...
},
set: function(target, key, value, receiver) {
...
},
deleteProperty(target, key) {
...
}
// ...以及其他 trap
}由于這里是極簡版本的實現(xiàn),那么我們就僅僅實現(xiàn) get 和 set 兩個 trap 就可以了,分別對應(yīng)依賴收集和觸發(fā)響應(yīng)的邏輯。
依賴收集
對于依賴收集的實現(xiàn),由于是極簡版本,實現(xiàn)的前提如下:
不考慮對象的嵌套
不考慮集合類型
不考慮基礎(chǔ)類型
不考慮對代理對象的處理
哈哈,基本這四點排除之后,這個依賴收集函數(shù)就會很輕很薄,如下:
function(target, key: string, receiver) {
// 僅僅在某個 effect 內(nèi)部進(jìn)行依賴收集
if (currentEffect) {
if (effectMap.has(key)) {
const effects = effectMap.get(key);
if (effects.indexOf(currentEffect) === -1) {
effects.push(currentEffect);
}
} else {
effectMap.set(key, [currentEffect]);
}
}
return Reflect.get(target, key, receiver);
}實現(xiàn)的邏輯很簡單,其實就是觀察者模式中注冊訂閱者的實現(xiàn)邏輯,值得注意的是,這里對于 target 的賦值邏輯,我們委托給 Reflect 來完成,雖然 target[key] 也是可以工作的,但是使用 Reflect 是更提倡的方式。
觸發(fā)響應(yīng)
觸發(fā)響應(yīng)的邏輯就比較簡單了,其實是對應(yīng)觀察者模式中,發(fā)布事件的邏輯,如下:
function(target, key: string, value, receiver) {
const result = Reflect.set(target, key, value, receiver);
if (effectMap.has(key)) {
effectMap.get(key).forEach(effect => effect());
}
return result;
}同樣,這里使用 Reflect 來對 target 進(jìn)行賦值操作,因為它會返回一個 boolean 值代表是否成功,而 set 這個 trap 也需要代表相同含義的值。
通過 reactive 方法來初始化代理對象
實現(xiàn)了數(shù)據(jù)劫持的代理邏輯之后,我們只需要在 reactive 這個方法中,返回一個代理對象的實例即可,還記的上文中我們在實現(xiàn)之前腦海中浮現(xiàn)的大致代碼框架嗎?
如下:
export function reactive(obj: any) {
const proxied = new Proxy(obj, {
get: function(target, key: string, receiver) {
if (currentEffect) {
if (effectMap.has(key)) {
const effects = effectMap.get(key);
if (effects.indexOf(currentEffect) === -1) {
effects.push(currentEffect);
}
} else {
effectMap.set(key, [currentEffect]);
}
}
return Reflect.get(target, key, receiver);
},
set: function(target, key: string, value, receiver) {
const result = Reflect.set(target, key, value, receiver);
if (effectMap.has(key)) {
effectMap.get(key).forEach(effect => effect());
}
return result;
}
});
return proxied;
}依賴收集的準(zhǔn)備工作
上文中提到了,對于依賴收集的工作,我們是有條件地進(jìn)行的,即在一個 effect 中,我們才會進(jìn)行收集,其他情況下的取值邏輯,我們則不會進(jìn)行依賴收集,因此,effect 方法正式為了實現(xiàn)這點而存在的,如下:
export function effect(fn: Function) {
const effected = function() {
fn();
};
currentEffect = effected;
effected();
currentEffect = undefined;
return effected;
}之所以實現(xiàn)如此簡單,是因為我們這里是極簡版本,不需要考慮諸如 readOnly 、異常以及收集時機等因素。可以發(fā)現(xiàn),就是將傳入的回調(diào)函數(shù)包裹在另一個方法中,然后將這個方法用 currentEffect 這個變量暫存,之后嘗試運行一下即可。當(dāng) effect 運行完畢之后,再將 currentEffect 置空,這樣就可以達(dá)到只在 effect 下進(jìn)行依賴收集的目的。
感謝各位的閱讀!關(guān)于“vue-next響應(yīng)式原理的示例分析”這篇文章就分享到這里了,希望以上內(nèi)容可以對大家有一定的幫助,讓大家可以學(xué)到更多知識,如果覺得文章不錯,可以把它分享出去讓更多的人看到吧!
另外有需要云服務(wù)器可以了解下創(chuàng)新互聯(lián)scvps.cn,海內(nèi)外云服務(wù)器15元起步,三天無理由+7*72小時售后在線,公司持有idc許可證,提供“云服務(wù)器、裸金屬服務(wù)器、高防服務(wù)器、香港服務(wù)器、美國服務(wù)器、虛擬主機、免備案服務(wù)器”等云主機租用服務(wù)以及企業(yè)上云的綜合解決方案,具有“安全穩(wěn)定、簡單易用、服務(wù)可用性高、性價比高”等特點與優(yōu)勢,專為企業(yè)上云打造定制,能夠滿足用戶豐富、多元化的應(yīng)用場景需求。
本文題目:vue-next響應(yīng)式原理的示例分析-創(chuàng)新互聯(lián)
本文地址:http://chinadenli.net/article10/dhsodo.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供全網(wǎng)營銷推廣、品牌網(wǎng)站制作、軟件開發(fā)、外貿(mào)網(wǎng)站建設(shè)、網(wǎng)站排名、網(wǎng)站建設(shè)
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)
猜你還喜歡下面的內(nèi)容