Vue.js 計算屬性的秘密


      計算屬性是一個很邪門的東西,只要在它的函數里引用了 data 中的某個屬性,當這個屬性發生變化時,函數仿佛可以嗅探到這個變化,並自動重新執行。

      上述代碼會源源不斷的打印出 b 的值。如果希望 a 依賴 data 中的 x 而變化,只需保證 a 函數中有 this.x 即可。如果函數中沒有出現 data 中的屬性,那么無論 data 中的屬性怎么變,a 對應的函數一次也不會執行。

      Vue 怎么知道計算屬性在函數中引用了哪個 data 屬性?這個函數又是怎么知道 data 屬性變了,而且只關心它內部引用的那個屬性,別的都不管?

      官方文檔對計算屬性的描述是:

      文檔的描述讓我的困惑更加困惑,還有這種操作?這特么是怎么做到的?

      Google 了一把,看了一篇三哥的博文(見文末),豁然開朗。

      我們簡單模擬實現一個計算屬性:a 變化時,b 自動跟着變化。

      由於涉及 Vue 的響應式綁定的原理,如果你對此不熟,最好先看看《Vue.js 雙向綁定的實現原理》

      少啰嗦,先看過程:

      1. 首先 b 屬性會被處理為存取器屬性,訪問 b 就會觸發其 get 函數

      2. 處理計算屬性 a 時,會執行 a 的函數,從而會執行 this.b,於是觸發 b 的 get 函數

      3. b 的 get 函數會添加 b 屬性的依賴項,而剛才在處理計算屬性過程中,a 已經作為依賴項被傳給了一個全局變量,b 的 get 函數會檢測到這個全局變量,並將其添加到自身的訂閱者列表中

      4. 對 b 賦予新的值時,會觸發其 set 函數,set 函數中會遍歷執行訂閱者,a 的值就是在這個時候更新的

      再看代碼:

(注:圖中數字僅作思路引導,並非與前文過程描述對應)

      測試一下,完美打印出 1, 2, 3, 4

      console.log(obj.b)

      obj.a += 1;

      console.log(obj.b);

      obj.a += 1;

      console.log(obj.b);

      obj.a += 1;

      console.log(obj.b);

     

      通過對存取器屬性、閉包和觀察者模式的綜合運用,Vue 巧妙的實現了計算屬性。現在再看官方文檔描述,是不是更通透了呢。

      可以看出,Vue 響應式系統的核心理念是“依賴”,DOM 節點之所以隨數據而變化,是因為節點依賴於數據,計算屬性之所以隨數據而變化,是因為計算屬性依賴於數據。做好響應式的關鍵就在於處理好依賴關系。

 

參考文章:https://skyronic.com/blog/vuejs-internals-computed-properties


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM