手把手教妳搓Vue響應式原理(壹)初識Vue響應式
手把手教妳搓Vue響應式原理(二)深度監測對象全部屬性
手把手教妳搓Vue響應式原理(三)observe 以及 ob
手把手教妳搓Vue響應式原理(四) 數組的響應式處理
之前已經將數據劫持已經全部完成了。
那麽,接下來,主要的要點就是在於兩點,依賴收集和觸發依賴更新。
它的意義主要在於控制哪些地方使用了這個變量,然後,按照最小的開銷來更新視圖 。
首先,要先明白,依賴是什麽,比方說在我們的模板中有 {{a}} ,那麽,這個地方就有對於變量 a 的依賴。
在模板編譯的時候,就會觸發 a 變量的 getter 。
然後,當我們執行 a++; 的時候,那麽,我們就要觸發依賴的更新,當初模板中 {{a}} 的地方,就要更新,是吧!
所以,我們都是 在 getter 中收集依賴,在 setter 中觸發依賴更新 。
這壹節的內容,主要就是用來專門講清楚這兩件事情。
依賴收集和觸發依賴更新主要由兩個類來完成, Dep 和 Watcher 。
Dep 和 Watcher 在設計模式中,就是 發布-訂閱者 的模式。
而依賴,妳可以理解為所謂的訂閱者。
Dep 說白了就是發布者,它的工作就是依賴管理,要知道哪些地方用到了這個變量,可能用到這個變量的地方有很多,所以,它會有多個訂閱者。
然後,每個變量都應該有屬於自己的 Dep ,因為每個變量所在的依賴位置是不壹樣的,所以他們的訂閱者也不壹樣。
然後在變量更新之後,就去通知所有的訂閱者(Watcher),我的變量更新了,妳們該觸發視圖更新了。
Watcher 說白了就是訂閱者,它接受 Dep 發過來的更新通知之後,就去執行視圖更新了。
它其實就是所謂的 watch 監聽器,變量改變之後,執行壹個回調函數。
我們先按照圖例來創建我們的 Dep 類
根據我們的需求:
Dep 我們在前面也說了,每個屬性都應該有它自己的 Dep ,用來管理依賴。
所以,首先,如果我們在 Observer 中創建 Dep,那不就可以了。畢竟 Observer 會遍歷到每壹個對象。
所以,很明顯,我們可以在 defineReactive 的 get 中收集依賴
因為有了 if(Dep.target) 的判斷,所以, 只有綁定 Watcher 的變量觸發 getter 時,才會添加依賴 。
這個 Dep.target 其實就是 Watcher 的實例
所以,很明顯,我們可以在 defineReactive 的 set 中收調用 notify() 方法告知 Watcher 實例,數據更新了。
至此, Dep 的所有職責,我們已經幫它完成了。
其實照道理應該有壹個刪除依賴,我們這裏就不再擴展了。
首先, Watcher 實例應該大家會相對而言更加好理解點,因為,我們有壹個 watch 偵聽器,大家壹定都很熟悉,這兩個其實壹樣。
我們先按照圖例來創建我們的 Watcher 類
根據我們的需求:
這個 parsePath 需要單獨拎出來說壹下,比方說我們現在有這麽壹個對象
我們要監聽到 a.b.c.d ,所以,我們需要下面的這種格式
所以,這個 get 很明顯就有點難度了。 我們需要通過循環 拿到 a.b 然後 .c 然後 .d。
我們將這個方法命名為 parsePath 。
入參接受我們的 b.c.d ,我們可以看到 第壹句執行之後 segments=['b','c','d'] ,然後進行第二層,這是返回了壹個方法,按照循環,那就是 obj=obj.b => obj=obj.c => obj=obj.d ,所以,就是返回壹個對象的 obj.b.c.d,相當於是遍歷字符串中的屬性樹。
在執行 a.b.c.d=55; 的同時,我們的控制臺就會輸出 ok 55 10 。
尚矽谷Vue源碼解析之數據響應式原理