【Vue原理】代理 Data - 源碼版

寫文章不容易,點個讚唄兄弟 專一 Vue 源碼分享,文章分爲白話版和 源碼版,白話版助於理解工做原理,源碼版助於瞭解內部詳情,讓咱們一塊兒學習吧 研究基於 Vue版本 【2.5.17】javascript

若是你以爲排版難看,請點擊 下面連接 或者 拉到 下面關注公衆號也能夠吧java

【Vue原理】代理 Data - 源碼版函數

寫這篇文章,我就是爲了記錄我對 Data 的一個疑問的探索,很簡短學習

data 的數據是怎麼能夠經過實例直接訪問的?this

第一想法,或許是,遍歷逐個複製?3d

可是其實並非,這裏涉及的一個詞,叫 【代理】代理

怎麼代理呢?聽我慢慢說,抓住逐個疑問,跟着我慢慢探索code

<br>對象

<br>blog


初始化數據

實例使用 initData 初始化數據,以下

function initData(vm) {     

    var data = vm.$options.data;    

    var keys = Object.keys(data);   

    var i = keys.length;

    data = vm._data =

    ( typeof data === 'function' ?

        data.call(vm) : data ) || {};   



    while (i--) {   

        var key = keys[i];  

        if (只要不是_和$開頭的屬性) {
    
            proxy(vm, "_data", key);     
        }   
    } 
    
}

首先,拿到 data 數據,若是data 是函數,就執行拿到返回值,不然直接拿設置的對象data

第二,保存data 數據

源碼中你能夠看到,把 data 保存到實例上了

vm._data = 
    typeof data === 'function' ? 
        data.call(vm) : data

初始化數據,是爲了拿到數據,而後放到存到實例上,做爲代理總部

<br>

<br>


二、代理開花

接下來,就放大招了,到了【data 代理】 的重點了,看上面的源碼最後

會遍歷data對象,若是屬性名不是 【_ 或者 $】 開頭的話,就會被設置代理

至於爲何避開那兩個開頭的屬性?

Vue官網也說明了

image

剩下的其餘屬性,會被設置代理,如今咱們來看設置代理的那句話

proxy(vm,"_data",key)

proxy 是什麼?不要急,等我放上源碼

function proxy(target, sourceKey, key) {    

    Object.defineProperty(target, key, {

        get() {            

            return this[sourceKey][key]

        },

        set(val) {            

            this[sourceKey][key] = val;

        }
    });
}

明白嗎?經過 Object.defineProperty 設置 get 和 set 函數,來達到代理,移花接木的過程

可能這麼看不太直觀,我以一個屬性爲例寫清楚點

image

因而就會設置成這樣

image

下面是給 _data 屬性設置響應式的簡化代碼

image

這樣的做用,有四個

一、能夠直接經過 vm 訪問到name

簡化寫法,你看看 React 這個比,訪問 state,須要 http://this.state.xxx 寫多一層 很麻煩啊,Vue 作了一層代理就很好,可是呢,成本會大一些

二、保證數據統一

若是是開篇想的那樣,逐個賦值,數據改變的時候,就要同時維護兩份啊,簡直是地獄啊。可是 methods 的處理是直接複製到實例上的

三、不影響依賴收集

當訪問 【vm.name】,觸發代理 【vm.name 設置的get】,就會訪問 【vm._data.name】 ,從而觸發總部 【vm._data.name 設置的get】,這個get 用來依賴收集。最後徹底不會影響

四、不影響依賴更新

賦值 【vm.name】,觸發代理 【vm.name 設置的 set】,就會直接賦值給總部 【vm._data.name】 ,從而觸發 【vm._data.name 設置的set 】,這個set,用來依賴更新。最後徹底不會影響

相關文章
相關標籤/搜索