vue.js源碼- 剖析observer,dep,watch如何具體的實現數據雙向綁定

Vue雙向數據綁定的核心和基礎api是Object.defineProperty,其內部真正參與數據雙向綁定流程的主要有Obderver、Dep和Watcher,基於defineProperty和發佈者訂閱者模式,最終實現數據的雙向綁定。那麼Obderver、Dep和Watcher是如何具體配合工做的呢?下面就來理一理。
vue

看此文章以前你須要對vue的雙向數據綁定有必定的理解。若不瞭解可移步:vue.js源碼解讀系列 - 雙向綁定具體如何初始化和工做git

看到這裏就當你對雙向數據綁定已經有必定的理解:github

提示:要看懂此篇文章你須要對vue的mvvm有必定的瞭解,並須要和專一的去理解,或者對照源碼跟着走,否則就很難真的看懂。

在這裏把雙向數據綁定分爲兩個流程: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 ,我也說了它就是一個Watcher實例化對象,你是否是很想搞懂它到底在哪裏賦值的呢,不急請跟着我下面的代碼看看。




搞懂了Dep.target等於一個Watche對象,如今繼續回到以前的思路看watcher.addDep作了什麼。學習



就這樣依賴收集的流程就走完了,是否感受很繞。

總結:依賴收集最終在 watcher.newDeps 中push了閉包中傳過來的dep對象,在dep.subs中push了初始化Vue是簡歷的Watcher對象,這個對象的,this.getter = expOrFn,傳過來的expOrFn是後期數據更新頁面渲染的核心步驟,須要沉下心來好好去理理。


二、視圖更新流程:

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方法,訂閱者發佈者的設計思路,巧妙的組織代碼,值得咱們很深刻的去學習和理解,從而促使咱們更好的去使用它。謝謝尤大的無私奉獻,讓咱們提升了生產力,把更多的精力花到業務邏輯中去。

原文地址:github.com/wangweiange…

相關文章
相關標籤/搜索