Vue雙向數據綁定的核心和基礎api是Object.defineProperty,其內部真正參與數據雙向綁定流程的主要有Obderver、Dep和Watcher,基於defineProperty和發佈者訂閱者模式,最終實現數據的雙向綁定。那麼Obderver、Dep和Watcher是如何具體配合工做的呢?下面就來理一理。
vue
看此文章以前你須要對vue的雙向數據綁定有必定的理解。若不瞭解可移步:vue.js源碼解讀系列 - 雙向綁定具體如何初始化和工做git
看到這裏就當你對雙向數據綁定已經有必定的理解:github
在這裏把雙向數據綁定分爲兩個流程:api
observe ->
walk ->
defineReactive ->
get ->
dep.depend() ->
watcher.addDep(new Dep()) ->
watcher.newDeps.push(dep) ->
dep.addSub(new Watcher()) ->
dep.subs.push(watcher)複製代碼
依賴收集會通過以上流程,最終watcher.newDeps數組中存放dep列表,dep.subs數組中存放watcher列表。數組
new Vue({
data(){
return {
name:'zane',
sex:'男'
}
}
})複製代碼
有上面這個data,實際上頁面只使用到了name,並無使用age,根據Object.defineProperty的轉換,若是咱們設置了this.sex='女',那麼Vue也會去執行一遍虛擬DOM的比較,這樣就無形的浪費了一些性能,所以才須要作依賴收集,界面用到了就收集,沒有用到就不收集。bash
咱們跟着流程走來理一遍源碼:閉包
直接進入Object.defineProperty的get方法:mvvm
考驗你閉包能力的時候到了,這個dep對象就是一個閉包。記下來咱們看看dep.depend()方法的實現。性能
搞懂了Dep.target等於一個Watche對象,如今繼續回到以前的思路看watcher.addDep作了什麼。學習
就這樣依賴收集的流程就走完了,是否感受很繞。
set ->
dep.notify() ->
subs[i].update() ->
watcher.run() || queueWatcher(this) ->
watcher.get() || watcher.cb ->
watcher.getter() ->
vm._update() ->
vm.__patch__()複製代碼
視圖更新會通過以上流程,最終調用Vue的虛擬Dom diff過程實時更新界面視圖
走到此處後面我就不去跟蹤了,後面會調用vm.__patch__ 方法,進而執行虛擬DOM的diff過程實時的更新界面。
要很好的理解vue的數據雙向綁定就要比較耐心,沉下心來慢慢理解,同時也須要對vue的源碼有個大體的理解,否則你只會看的愈來愈煩躁愈來愈沒有信心。
vue很好的利用了Object.defineProperty方法的 get和set方法,訂閱者發佈者的設計思路,巧妙的組織代碼,值得咱們很深刻的去學習和理解,從而促使咱們更好的去使用它。謝謝尤大的無私奉獻,讓咱們提升了生產力,把更多的精力花到業務邏輯中去。