国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

【Vue原理】依賴收集 - 源碼版之引用數(shù)據(jù)類型

vvpvvp / 1877人閱讀

摘要:寫(xiě)文章不容易,點(diǎn)個(gè)贊唄兄弟專注源碼分享,文章分為白話版和源碼版,白話版助于理解工作原理,源碼版助于了解內(nèi)部詳情,讓我們一起學(xué)習(xí)吧研究基于版本如果你覺(jué)得排版難看,請(qǐng)點(diǎn)擊下面鏈接或者拉到下面關(guān)注公眾號(hào)也可以吧原理依賴收集源碼版之引用數(shù)據(jù)類型上

寫(xiě)文章不容易,點(diǎn)個(gè)贊唄兄弟
專注 Vue 源碼分享,文章分為白話版和 源碼版,白話版助于理解工作原理,源碼版助于了解內(nèi)部詳情,讓我們一起學(xué)習(xí)吧
研究基于 Vue版本 【2.5.17】

如果你覺(jué)得排版難看,請(qǐng)點(diǎn)擊 下面鏈接 或者 拉到 下面關(guān)注公眾號(hào)也可以吧

【Vue原理】依賴收集 - 源碼版之引用數(shù)據(jù)類型

上一篇,我們已經(jīng)分析過(guò)了 基礎(chǔ)數(shù)據(jù)類型的 依賴收集

【Vue原理】依賴收集 - 源碼版之基本數(shù)據(jù)類型

這一篇內(nèi)容是針對(duì) 引用數(shù)據(jù)類型的數(shù)據(jù)的 依賴收集分析,因?yàn)橐妙愋蛿?shù)據(jù)要復(fù)雜些,必須分開(kāi)寫(xiě)

文章很長(zhǎng),高能預(yù)警,做好準(zhǔn)備耐下心好,肯定還是有點(diǎn)收獲的

但是兩個(gè)類型的數(shù)據(jù)的處理,又有很多重復(fù)的地方,所以打算只寫(xiě)一些差異性的地方就好了,否則顯得廢話很多

兩個(gè)步驟,都有不同的地方

1、數(shù)據(jù)初始化

2、依賴收集

數(shù)據(jù)初始化流程

如果數(shù)據(jù)類型是引用類型,需要對(duì)數(shù)據(jù)進(jìn)行額外的處理。

處理又分了 對(duì)象 和 數(shù)組 兩種,會(huì)分開(kāi)來(lái)講

1對(duì)象

1、遍歷對(duì)象的每個(gè)屬性,同樣設(shè)置響應(yīng)式,假設(shè)屬性都是基本類型,處理流程跟上一篇一樣

2、每個(gè)數(shù)據(jù)對(duì)象會(huì)增加一個(gè) ob 屬性

比如設(shè)置一個(gè) child 的數(shù)據(jù)對(duì)象

下圖,你可以看到 child 對(duì)象處理之后添加了一個(gè) ob 屬性

ob_ 屬性有什么用啊?

你可以觀察到,__ob__ 有一個(gè) dep 屬性,這個(gè) dep 是不是有點(diǎn)屬性,是的,在上一篇基礎(chǔ)數(shù)據(jù)類型中講過(guò)

那么這個(gè) ob 屬性有什么用啊?

你可以觀察到,__ob__ 有一個(gè) dep 屬性,這個(gè) dep 是不是有點(diǎn)屬性,是的,在上一篇基礎(chǔ)數(shù)據(jù)類型中講過(guò)

dep 正是存儲(chǔ)依賴的地方

比如 頁(yè)面引用了 數(shù)據(jù)child,watch 引用了數(shù)據(jù)child,那么child 就會(huì)把這個(gè)兩個(gè)保存在 dep.subs 中

dep.subs = [ 頁(yè)面-watcher,watch-watcher ]

但是,在上一篇基礎(chǔ)類型種, dep 是作為閉包存在的啊,并不是保存在什么【__ob__.dep】 中啊

沒(méi)錯(cuò),這就是 引用類型 和 基礎(chǔ)類型的區(qū)別了

基礎(chǔ)數(shù)據(jù)類型,只使用 【閉包dep】 來(lái)存儲(chǔ)依賴

引用數(shù)據(jù)類型,使用 【閉包dep】 和 【 __ob__.dep】 兩種來(lái)存儲(chǔ)依賴

什么?你說(shuō)閉包dep 在哪里?好吧,在 defineReactive 的源碼中,你去看看這個(gè)方法的源碼,下面有

那么,為什么,引用類型需要 使用__ob__.dep 存儲(chǔ)依賴呢?

首先,明確一點(diǎn),存儲(chǔ)依賴,是為了數(shù)據(jù)變化時(shí)通知依賴,所以 __ob__.dep 也是為了變化后的通知

閉包 dep 只存在 defineReactive 中,其他地方無(wú)法使用到,所以需要保存另外一個(gè)在其他地方使用

在其他什么地方會(huì)使用呢?

在Vue掛載原型上的方法 set 和 del 中,源碼如下

function set(target, key, val) {    

    var ob = (target).__ob__;    

    // 通知依賴更新
    ob.dep.notify();
}
Vue.prototype.$set = set;
function del(target, key) {    

    var ob = (target).__ob__;    

    delete target[key];    

    if (!ob)  return

    // 通知依賴更新
    ob.dep.notify();

}
Vue.prototype.$delete = del;

這兩個(gè)方法,大家應(yīng)該都用過(guò),為了給對(duì)象動(dòng)態(tài) 添加屬性和 刪除屬性

但是如果直接添加屬性或者刪除屬性,Vue 是監(jiān)聽(tīng)不到的,比如下面這樣

child.xxxx=1

delete child.xxxx

所以必須要通過(guò) Vue 包裝過(guò)的方法 set 和 del 來(lái)操作

在 set 和 del 執(zhí)行完,是需要通知依賴更新的,但是我怎么通知?

此時(shí),【__ob__.dep】 就發(fā)揮作用了!就因?yàn)橐蕾嚩嗍占艘环菰?__ob__.dep 中

使用就是上面一句話,通知更新

ob.dep.notify();

2、數(shù)組

1、需要遍歷數(shù)組,可能數(shù)組是對(duì)象數(shù)組,如下面

[{name:1},{name:888}]

遍歷時(shí),如果遇到子項(xiàng)是對(duì)象的,會(huì)跟上面解析對(duì)象一樣操作

2、給數(shù)組保存一個(gè) ob 屬性

比如設(shè)置一個(gè) arr 數(shù)組

看到 arr數(shù)組 加多了一個(gè) ob 屬性

其實(shí)這個(gè) ob 屬性 和 上一段講對(duì)象 的作用是差不多的,這里也只是說(shuō) __ob__.dep

數(shù)組中的 __ob__.dep 存儲(chǔ)的也是依賴,給誰(shuí)用呢?

給 Vue 封裝的數(shù)組方法使用,要知道要想數(shù)組變化也被監(jiān)聽(tīng)到,是必須使用Vue封裝的數(shù)組方法的,否則無(wú)法實(shí)時(shí)更新

這里舉重寫(xiě)方法之一 push,其他的還有 splice 等,Vue 官方文檔已經(jīng)有過(guò)說(shuō)明

var original = Array.prototype.push;

Array.prototype.push = function() {    

    var args = [],

    len = arguments.length;    

    // 復(fù)制 傳給 push 等方法的參數(shù)
    while (len--) args[len] = arguments[len];

    // 執(zhí)行 原方法
    var result = original.apply(this, args);    

    var ob = this.__ob__;    

    // notify change
    ob.dep.notify();    

    return resul
}

看到在執(zhí)行完 數(shù)組方法之后,同樣需要通知依賴更新,也就是通知 __ob__.dep 中收集的依賴去更新

現(xiàn)在,我們知道了,響應(yīng)式數(shù)據(jù)對(duì) 引用類型做了什么額外的處理,主要是加了一個(gè) ob 屬性

我們已經(jīng)知道了 ob 有什么用,現(xiàn)在看看源碼是怎么添加 ob

// 初始化Vue組件的數(shù)據(jù)

function initData(vm) {    

    var data = vm.$options.data;

    data = vm._data = 

        typeof data === "function" ? 

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

    ....遍歷 data 數(shù)據(jù)對(duì)象的key ,重名檢測(cè),合規(guī)檢測(cè)
    observe(data, true);

}

function observe(value) {    

    if (Array.isArray(value) || typeof value == "object") {
        ob = new Observer(value);
    }    
    return ob
}
function Observer(value) {   

    // 給對(duì)象生成依賴保存器
    this.dep = new Dep();   

    // 給 每一個(gè)對(duì)象 添加一個(gè)  __ob__ 屬性,值為 Observer 實(shí)例
    value.__ob__ = this

    if (Array.isArray(value)) { 

        // 遍歷數(shù)組,每一項(xiàng)都需要通過(guò) observe 處理,如果是對(duì)象就添加 __ob__
        for (var i = 0, l =value.length; i < l; i++) {
            observe(value[i]);
        }

    } else {        

        var keys = Object.keys(value);     

        // 給對(duì)象的每一個(gè)屬性設(shè)置響應(yīng)式
        for (var i = 0; i < keys.length; i++) {
            defineReactive(value, keys[i]);
        }
    }
};

源碼的流程跟上一篇差不多,只是處理引用數(shù)據(jù)類型會(huì)增加多幾行源碼的額外處理

我們之前只說(shuō)了一種對(duì)象數(shù)據(jù)類型,比如下面這樣

如果會(huì)嵌套多層對(duì)象呢?比如這樣,會(huì)怎么處理

沒(méi)錯(cuò),Vue 會(huì)遞歸處理,當(dāng)遍歷屬性,使用 defineReactive 處理時(shí),遞歸調(diào)用 observe 處理(源碼標(biāo)紅加粗)

如果值是對(duì)象,那么同樣給 值加多一個(gè) ob

如果不是,那么正常往下走,設(shè)置響應(yīng)式

源碼如下

function defineReactive(obj, key, value) {  

    // dep 用于中收集所有 依賴我的 東西
    var dep = new Dep();    
    var val  = obj[key] 

    // 返回的 childOb 是一個(gè) Observer 實(shí)例
    // 如果值是一個(gè)對(duì)象,需要遞歸遍歷對(duì)象
    var childOb = observe(val);    

    Object.defineProperty(obj, key, {
        get() {...依賴收集跟初始化無(wú)關(guān),下面會(huì)講},
        set() { .... }
    });
}

畫(huà)一個(gè)流程圖,僅供參考

哈哈哈,上面寫(xiě)得好長(zhǎng)啊,是有點(diǎn),但是沒(méi)辦法,想說(shuō)詳細(xì)點(diǎn)啊,好吧,還有一段,但是比較短一些哈哈哈,反正看完的人,我jio 得很厲害了,答應(yīng)我,如果你仔細(xì)看完了,評(píng)論一下好嗎,讓我知道有人仔細(xì)看了

依賴收集流程

收集流程,就是重點(diǎn)關(guān)注 Object.defineProperty 設(shè)置的 get 方法了

跟 基礎(chǔ)類型數(shù)據(jù) 對(duì)比,引用類型的 收集方法也只是多了幾行處理,差異在兩行代碼

childOb.dep.depend,被我 簡(jiǎn)單化為 childOb.dep.addSub(Dep.target)
dependArray(value)
可以先看下源碼,如下

function defineReactive(obj, key, value) {    

    var dep = new Dep();    
    var val  = obj[key]    
    var childOb = observe(val);    

    Object.defineProperty(obj, key, {
        get() {            
            var value = val            
            if (Dep.target) {

                // 收集依賴進(jìn) dep.subs
                dep.addSub(Dep.target);

                // 如果值是一個(gè)對(duì)象,Observer 實(shí)例的 dep 也收集一遍依賴
                if (childOb) {
                    childOb.dep.addSub(Dep.target)          
                    if (Array.isArray(value)) {
                        dependArray(value);
                    }
                }
            }            
            return value
        }
    });
}

上面的源碼,混雜了 對(duì)象和 數(shù)組的處理,我們分開(kāi)說(shuō)

1、對(duì)象

在數(shù)據(jù)初始化的流程中,我們已經(jīng)知道值是對(duì)象的話,會(huì)存儲(chǔ)多一份依賴在 __ob__.dep 中

就只有一句話

childOb.dep.depend();

數(shù)組還有另外一個(gè)處理,就是

dependArray(value);

看下源碼,如下

function dependArray(value) {    

    for (var i = 0, l = value.length; i < l; i++) {        

        var e = value[i];        

        // 只有子項(xiàng)是對(duì)象的時(shí)候,收集依賴進(jìn) dep.subs
        e && e.__ob__ && e.__ob__.dep.addSub(Dep.target);   
     

        // 如果子項(xiàng)還是 數(shù)組,那就繼續(xù)遞歸遍歷
        if (Array.isArray(e)) {
            dependArray(e);
        }
    }
}

顯然,是為了防止數(shù)組里面有對(duì)象,從而需要給 數(shù)組子項(xiàng)對(duì)象也保存一份

你肯定會(huì)問(wèn),為什么子項(xiàng)對(duì)象也要保存一份依賴?

1、頁(yè)面依賴了數(shù)組,數(shù)組子項(xiàng)變化了,是不是頁(yè)面也需要更新?但是子項(xiàng)內(nèi)部變化怎么通知頁(yè)面更新?所以需要給子項(xiàng)對(duì)象也保存一份依賴?

2、數(shù)組子項(xiàng)數(shù)組變化,就是對(duì)象增刪屬性,必須用到Vue封裝方法 set 和 del,set 和 del 會(huì)通知依賴更新,所以子項(xiàng)對(duì)象也要保存

看個(gè)栗子

頁(yè)面模板

看到數(shù)組的數(shù)據(jù),就存在兩個(gè) ob

總結(jié)

到這里,就可以很清楚,引用類型和 基礎(chǔ)類型的處理差異了

1、引用類型會(huì)多添加一個(gè) __ob__屬性,其中包含 dep,用于存儲(chǔ) 收集到的依賴

2、對(duì)象使用 __ob__.dep,作用在 Vue 自定義的方法 set 和 del 中

3、數(shù)組使用 __ob__.dep,作用在 Vue 重寫(xiě)的數(shù)組方法 push 等中

終于寫(xiě)完了,真的好長(zhǎng),但是我覺(jué)得值得了

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/109952.html

相關(guān)文章

  • Vue原理依賴收集 - 源碼版之基本數(shù)據(jù)類型

    摘要:當(dāng)東西發(fā)售時(shí),就會(huì)打你的電話通知你,讓你來(lái)領(lǐng)取完成更新。其中涉及的幾個(gè)步驟,按上面的例子來(lái)轉(zhuǎn)化一下你買東西,就是你要使用數(shù)據(jù)你把電話給老板,電話就是你的,用于通知老板記下電話在電話本,就是把保存在中。剩下的步驟屬于依賴更新 寫(xiě)文章不容易,點(diǎn)個(gè)贊唄兄弟專注 Vue 源碼分享,文章分為白話版和 源碼版,白話版助于理解工作原理,源碼版助于了解內(nèi)部詳情,讓我們一起學(xué)習(xí)吧研究基于 Vue版本 【...

    VincentFF 評(píng)論0 收藏0
  • Vue原理依賴更新 - 源碼

    摘要:寫(xiě)文章不容易,點(diǎn)個(gè)贊唄兄弟專注源碼分享,文章分為白話版和源碼版,白話版助于理解工作原理,源碼版助于了解內(nèi)部詳情,讓我們一起學(xué)習(xí)吧研究基于版本如果你覺(jué)得排版難看,請(qǐng)點(diǎn)擊下面鏈接或者拉到下面關(guān)注公眾號(hào)也可以吧原理依賴更新源碼版如果對(duì)依賴收集完 寫(xiě)文章不容易,點(diǎn)個(gè)贊唄兄弟專注 Vue 源碼分享,文章分為白話版和 源碼版,白話版助于理解工作原理,源碼版助于了解內(nèi)部詳情,讓我們一起學(xué)習(xí)吧研究基于...

    moven_j 評(píng)論0 收藏0
  • Vue原理】Props - 源碼

    寫(xiě)文章不容易,點(diǎn)個(gè)贊唄兄弟專注 Vue 源碼分享,文章分為白話版和 源碼版,白話版助于理解工作原理,源碼版助于了解內(nèi)部詳情,讓我們一起學(xué)習(xí)吧研究基于 Vue版本 【2.5.17】 如果你覺(jué)得排版難看,請(qǐng)點(diǎn)擊 下面鏈接 或者 拉到 下面關(guān)注公眾號(hào)也可以吧 【Vue原理】Props - 源碼版 今天記錄 Props 源碼流程,哎,這東西,就算是研究過(guò)了,也真是會(huì)隨著時(shí)間慢慢忘記的。 幸好我做...

    light 評(píng)論0 收藏0
  • Vue原理】NextTick - 源碼版 之 服務(wù)Vue

    寫(xiě)文章不容易,點(diǎn)個(gè)贊唄兄弟專注 Vue 源碼分享,文章分為白話版和 源碼版,白話版助于理解工作原理,源碼版助于了解內(nèi)部詳情,讓我們一起學(xué)習(xí)吧研究基于 Vue版本 【2.5.17】 如果你覺(jué)得排版難看,請(qǐng)點(diǎn)擊 下面鏈接 或者 拉到 下面關(guān)注公眾號(hào)也可以吧 【Vue原理】NextTick - 源碼版 之 服務(wù)Vue 初次看的兄弟可以先看 【Vue原理】NextTick - 白話版 簡(jiǎn)單了解下...

    Acceml 評(píng)論0 收藏0
  • Vue原理】VModel - 源碼版之input詳解

    摘要:因?yàn)槭ソ裹c(diǎn)之后被強(qiáng)制更新了一波嗯,這就是的作用,把頁(yè)面上的顯示值也過(guò)濾一遍 寫(xiě)文章不容易,點(diǎn)個(gè)贊唄兄弟專注 Vue 源碼分享,文章分為白話版和 源碼版,白話版助于理解工作原理,源碼版助于了解內(nèi)部詳情,讓我們一起學(xué)習(xí)吧研究基于 Vue版本 【2.5.17】 如果你覺(jué)得排版難看,請(qǐng)點(diǎn)擊 下面鏈接 或者 拉到 下面關(guān)注公眾號(hào)也可以吧 【Vue原理】VModel - 源碼版之input詳...

    leanxi 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<