最新 vue-next 的原始碼發布了,雖然是 pre-alpha 版本,但這時候其實是閱讀原始碼的比較好的時機。在 vue 中,比較重要的東西當然要數它的響應式系統,在之前的版本中,已經有若干篇文章對它的響應式原理和實現進行了介紹,這裡就不贅述了。在 vue-next 中,其實現原理和之前還是相同的,即通過觀察者模式和資料劫持,只不過對其實現方式進行了改變。
對於解析原理的文章,我個人是比較喜歡那種「小白」風格的文章,即不要摘錄特別多的**,也不要闡述一些很深奧的原理與概念。在我剛接觸 react 的時候,還記得有一篇利用 jquery 來介紹 react 的文章,從簡入繁,面面俱到,其背後闡述的知識點對我後來學習 react 起到很多的幫助。
如有錯誤,還望指正。
我們大體要實現的效果如下面的**所示:
// 實現兩個方法 reactive 和 effect
const state = reactive()
effect(() => )
state.count++ // 輸入 count: 1
可以發現我們熟悉的依賴收集階段(同時也是觀察者模式的訂閱過程),是在 effect 中進行的,依賴收集的準備工作(即資料劫持邏輯),是在 reactive 中進行的,而資料變化的觸發響應的邏輯在後面的 state.count++ **執行時進行(同時也是觀察者模式的發布過程),之後便會執行之前傳入 effect 內部的**函式並輸入 count: 1。
由於 vue-next 用 ts 進行了重寫,這裡我也使用 ts 來實現這個極簡版本的響應式系統。主要涉及到的型別和公共變數如下:
type effect = function;
type effectmap = map;
let currenteffect: effect;
const effectmap: effectmap = new map();
在之前的版本中,vue 利用 object.defineproperty 中的 setter 和 getter 來對資料物件進行劫持,vue-next 則通過 proxy。眾所周知,object.defineproperty 所實現的資料劫持是有一定限制的,而 proxy 就會強大很多。
首先,我們在腦後中,設想一下如何使用 proxy 來實現資料劫持呢?很簡單,大體結構如下所示:
export function reactive(obj)
這裡的 handlers 是宣告如何處理各個 trap 的邏輯,比如:
const handlers = ,
set: function(target, key, value, receiver) ,
deleteproperty(target, key)
// ...以及其他 trap
}
由於這裡是極簡版本的實現,那麼我們就僅僅實現 get 和 set 兩個 trap 就可以了,分別對應依賴收集和觸發響應的邏輯。
對於依賴收集的實現,由於是極簡版本,實現的前提如下:
哈哈,基本這四點排除之後,這個依賴收集函式就會很輕很薄,如下:
function(target, key: string, receiver)
} else
}return reflect.get(target, key, receiver);
}
實現的邏輯很簡單,其實就是觀察者模式中註冊訂閱者的實現邏輯,值得注意的是,這裡對於 target 的賦值邏輯,我們委託給 reflect 來完成,雖然 target[key] 也是可以工作的,但是使用 reflect 是更提倡的方式。
觸發響應的邏輯就比較簡單了,其實是對應觀察者模式中,發布事件的邏輯,如下:
function(target, key: string, value, receiver)
return result;
}
同樣,這裡使用 reflect 來對 target 進行賦值操作,因為它會返回乙個 boolean 值代表是否成功,而 set 這個 trap也需要代表相同含義的值。
實現了資料劫持的**邏輯之後,我們只需要在 reactive 這個方法中,返回乙個**物件的例項即可,還記的上文中我們在實現之前腦海中浮現的大致**框架嗎?
如下:
export function reactive(obj: any)
} else
}return reflect.get(target, key, receiver);
},set: function(target, key: string, value, receiver)
return result;
}});
return proxied;
}
上文中提到了,對於依賴收集的工作,我們是有條件地進行的,即在乙個 effect 中,我們才會進行收集,其他情況下的取值邏輯,我們則不會進行依賴收集,因此,effect 方法正式為了實現這點而存在的,如下:
export function effect(fn: function) ;
currenteffect = effected;
effected();
currenteffect = undefined;
return effected;
}
之所以實現如此簡單,是因為我們這裡是極簡版本,不需要考慮諸如 readonly 、異常以及收集時機等因素。可以發現,就是將傳入的**函式包裹在另乙個方法中,然後將這個方法用 currenteffect 這個變數暫存,之後嘗試執行一下即可。當 effect 執行完畢之後,再將 currenteffect 置空,這樣就可以達到只在 effect 下進行依賴收集的目的。
資源搜尋**大全
廣州vi設計公司
這個極簡的響應式系統雖然能用,但是有很多未考慮的因素,其實就是在上文中被我們忽略的那些前提條件,這裡再列舉一下,並給出源**中的解法:
vue響應式布局 Vue 響應式原理
vue2 的資料偵測 在 src observer 目錄裡面,元件例項在初始化時,會呼叫 observe 函式處理 data function initdata vm observe 改寫了所有物件屬性的 getter setter 和陣列原型上的 7 個會改寫陣列方法,從而讓 data 變成可響應...
vue響應式原理
響應式系統是vue框架核心的部分,資料物件僅僅是普通的 js物件。當我們改變資料時,檢視也會被改變,本文就來 一下vue 的響應式原理。vue響應式的核心是使用了es5 新增的api object.defineproperty 因此vue不支援ie8 object.defineproperty的作用...
vue響應式原理
要了解響應式原理首先應該知道什麼是響應式 更改 vue的響應式原理是什麼 vue資料的雙向繫結是通過資料劫持結合發布訂閱模式,偵測到資料變化,然後通過object.defineproperty 物件對每個屬性的getter和setter進行劫持。當讀取 data 中的資料時自動呼叫 get 方法,當...