很多介紹vue源碼的文章對computed怎麽計算值講的很清楚,但是對computed 怎麽搜集到依賴它的視圖渲染watcher,以及怎麽去通知對應的渲染watcher去更新講解的很模糊或者幹脆壹筆帶過。這篇文章主要講解——computed watcher是怎麽搜集到訂閱它的渲染watcher。
文件在src/core/instance/state.js
當組件讀取computed a的值的時候會執行 computedGetter函數,先是通過
計算出computed函數的值,然後通過
進行依賴搜集。
Dep.target指向當前組件的渲染watcher,進入watcher.depend()看看是怎麽進行依賴搜集的
文件位於 src/core/observer/watcher.js
第壹個問題:this.deps的賦值
是在cleanupDeps函數中執行this.deps = this.newDeps,所以要看cleanupDeps在哪裏被調用的,以及this.newDeps中的值是哪裏產生的
get函數是在computed 通過watcher.evaluate()計算值的時候被調用的,講解下這個函數的核心操作
這個this是計算屬性的watcher,調用dep.js中的
作用是放到棧頂,同時將計算屬性的watcher賦值給Dep.taget
會調用 計算屬性a的函數
由於引用到了i,所以會觸發i的get 函數,就會調用dep.depend(),實際上是i的依賴搜集,這裏的dep對象屬於i
dep.depend() 位於src/core/observer/dep.js
這裏的Dep.target就是上面保存的computed watcher實例,會執行watcher中的addDep,這裏的this就是i的dep實例
文件位於 src/core/observer/watcher.js
做了兩件事
把棧頂的watcher彈出,改變Dep.target的指向,此時指向組件的渲染watcher
這壹步就是 將this.newDeps的值賦給this.deps,此時this.deps中的數組中的對象其實就是i的dep實例
再回到 watcher.depend()
this.deps[i].depend() 這裏就是執行
此時Dep.target是組件的渲染watcher,所以實現的邏輯是組件渲染watcher調用addDep(this),其實就是持有i的dep,最終被i搜集到依賴。
轉了這麽大壹圈,實際上是為了讓組件的watcher被計算屬性中引用的data變量搜集到,這也不難理解,既然組件依賴computed的變化,當然也依賴computed中的值的變化,示例中computed中的值變化來自於i的變化,所以當i變化時,就讓去通知計算屬性的watcher去重新計算,通知組件watcher重新渲染。
對於data中變量的響應式原理和依賴搜集、派發更新可以參考我的這篇文章
從源碼的角度分析Vue視圖更新和nexttick機制
參考:
/post/6877451301618352141