vue-computed實現原理


1,計算屬性的用法

vue中計算屬性能夠實現一個數據依賴其他數據的變化而變化,話不多說先上代碼

 1 new Vue({
 2         data:{
 3             a:1
 4         },
 5         mounted(){
 6             const that = this
 7             setTimeout(function(){
 8                 that.a = 2
 9             },2000)
10         },
11         computed:{
12             b:function(){
13                 console.log("現在b的值是",this.a+1)
14                 return this.a + 1
15             }
16         }
17     })

在computed中定義一個 計算屬性(函數),這個函數中涉及到data中的所有數據,都會被收集起來,將他們作為這個屬性計算的依賴,當這些依賴發生變化時,就會執行這個計算屬性對應的函數。比如上面的例子中,b的計算屬性函數中有this.a,a是data中的數據,那a將會作為b計算屬性的一個依賴被收集起來,第8行中that.a = 2,此時a的值發生變化,觸發b的計算屬性函數,這樣就完成了一次計算。

2,計算屬性的原理

有這么一個方法 Object.defineProperty(),先讓我們看看這個方法是怎么用的。

Object.defineProperty() 方法會直接在一個對象上定義一個新屬性,或者修改一個對象的現有屬性,並返回此對象。

 Object.defineProperty(obj, prop, descriptor) 

參數:

obj 要定義屬性的對象。
prop 要定義或修改的屬性的名稱或 Symbol
descriptor 要定義或修改的屬性描述符。
其中第三個參數descriptor是一個json,有興趣的可以去 Object.defineProperty()研究一下。我們這里主要是看set(屬性的setter函數),get(屬性的getter函數)
話不多說,先上代碼
var obj = {}
    Object.defineProperty(obj,"a",{
        set:function(val){
            console.log("set函數執行")
            this._a = val // 定義一個_a作為一個私有屬性,來記錄a屬性的值
        },
        get:function(){
            console.log("get函數執行")
            return this._a
        }
    })
    obj.a = "123"
    // set函數執行
    console.log(obj.a)
    // get函數執行
    // 123

 上面的代碼 可以看出 只要執行obj.a = xxx 就會執行 obj中a屬性的set函數,只要執行obj.a 就會調用obj中a屬性的get函數

3,屬性計算的實現

vue中屬性計算利用函數閉包和對象屬性set,get函數 完美實現

 1    var Dep = null  
 2     function defineReactive(obj,key,val){
 3         var deps = [] // deps 收集依賴用
 4         Object.defineProperty(obj,key,{
 5             get:function(){
 6                 if(Dep){
 7                     deps.push(Dep)
 8                 }
 9                 return val
10             },
11             set:function(newVal){
12                 val = newVal;
13                 deps.forEach(func=>func()) // deps 在set函數中被引用 形成閉包
14             }
15         })
16     }
17 
18     function defineComputed(obj,key,func){
19         func = func.bind(obj)
20         var value
21         Dep = function(){
22             value = func() // value 在此函數中被引用 形成閉包
23         }
24         value = func() // 執行一次 屬性計算函數,計算屬性函數中的this.a(36行)的執行,會執行a的get函數(5行),將計算屬性函數放到依賴項中(第7行)
25         Dep = null
26         Object.defineProperty(obj,key,{
27             get:function(){
28                 return value // value 在set函數中被引用 形成閉包
29             }
30         })
31     }
32 
33     var obj = {}
34     defineReactive(obj,"a",0)
35     defineComputed(obj,"b",function(){
36         var a = this.a
37         return a + 1
38     })

執行上面的代碼,在控制台輸入

 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);
 測試一下,完美打印出 1, 2, 3, 4
通過對存取器屬性、閉包和觀察者模式的綜合運用,Vue 巧妙的實現了計算屬性。現在再看官方文檔描述,是不是更通透了呢。 可以看出,Vue 響應式系統的核心理念是“依賴”,DOM 節點之所以隨數據而變化,是因為節點依賴於數據,計算屬性之所以隨數據而變化,是因為計算屬性依賴於數據。做好響應式的關鍵就在於處理好依賴關系。 

 


免責聲明!

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



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