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

資訊專欄INFORMATION COLUMN

【Vue原理】Mixins - 源碼版

gotham / 3574人閱讀

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

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

【Vue原理】Mixins - 源碼版

今天探索的是 mixins 的源碼,mixins 根據(jù)不同的選項(xiàng)類型會(huì)做不同的處理

篇幅會(huì)有些長,你知道的,有很多種選項(xiàng)類型的嘛,但不是很難。只是涉及源碼難免會(huì)有些煩,

不過這篇文章也不是給你直接看的,是為了可以讓你學(xué)習(xí)源碼的時(shí)候提供微薄幫助而已

如果不想看源碼的,可以看我的白話版

【Vue原理】Mixin - 白話版

我們也是要帶著兩個(gè)問題開始

1、什么時(shí)候開始合并

2、怎么合并

如果你覺得排版難看,請(qǐng)點(diǎn)擊下面原文鏈接 或者 關(guān)注公眾號(hào)【神仙朱】

什么時(shí)候合并

合并分為兩種

1、全局mixin 和 基礎(chǔ)全局options 合并

這個(gè)過程是先于你調(diào)用 Vue 時(shí)發(fā)生的,也是必須是先發(fā)生的。這樣mixin 才能合并上你的自定義 options

Vue.mixin = function(mixin) {
    this.options = mergeOptions(
        this.options, mixin
    );
    return this
};

基礎(chǔ)全局options 是什么?

就是 components,directives,filters 這三個(gè),一開始就給設(shè)置在了 Vue.options 上。所以這三個(gè)是最先存在全局options

Vue.options = Object.create(null);

["component","directive","filter"].forEach(function(type) {
    Vue.options[type + "s"] = Object.create(null);
});

這一步,是調(diào)用 Vue.mixin 的時(shí)候就馬上合并了,然后這一步完成 以后,舉個(gè)栗子

全局選項(xiàng)就變成下面這樣,然后每個(gè)Vue實(shí)例都需要和這全局選項(xiàng)合并

2、全局options和 自定義options合并

在調(diào)用Vue 的時(shí)候,首先進(jìn)行的就是合并

function Vue(options){
    vm.$options = mergeOptions(
        { 全局component,
                 全局directive,
                 全局filter 等....},
        options , vm
    );

    // ...處理選項(xiàng),生成模板,掛載DOM 等....
}

options 就是你自己傳進(jìn)去的對(duì)象參數(shù),然后跟 全局options 合并,全局options 是哪些,也已經(jīng)說過了

怎么合并

上面的代碼一直出現(xiàn)一個(gè)函數(shù) mergeOptions,他便是合并的重點(diǎn)

來看源碼

1、mergeOptions
function mergeOptions(parent, child, vm) {    

    // 遍歷mixins,parent 先和 mixins 合并,然后在和 child 合并
    if (child.mixins) {        

        for (var i = 0, l = child.mixins.length; i < l; i++) {
            parent = mergeOptions(parent, child.mixins[i], vm);
        }
    }    
    
    var options = {}, key;    

    // 先處理 parent 的 key,
    for (key in parent) {
        mergeField(key);
    }    

    // 遍歷 child 的key ,排除已經(jīng)處理過的 parent 中的key
    for (key in child) {        
        if (!parent.hasOwnProperty(key)) {
            mergeField(key);
        }
    }    

    // 拿到相應(yīng)類型的合并函數(shù),進(jìn)行合并字段,strats 請(qǐng)看下面
    function mergeField(key) {    

        // strats 保存著各種字段的處理函數(shù),否則使用默認(rèn)處理
        var strat = strats[key] || defaultStrat;    

        // 相應(yīng)的字段處理完成之后,會(huì)完成合并的選項(xiàng)
        options[key] = strat(parent[key], child[key], vm, key);
    }    
    return options
}

這段代碼看上去有點(diǎn)繞,其實(shí)無非就是

1、先遍歷合并 parent 中的key,保存在變量options

2、再遍歷 child,合并補(bǔ)上 parent 中沒有的key,保存在變量options

3、優(yōu)先處理 mixins ,但是過程跟上面是一樣的,只是遞歸處理而已

在上面實(shí)例初始化時(shí)的合并, parent 就是全局選項(xiàng),child 就是組件自定義選項(xiàng),因?yàn)?parent 權(quán)重比 child 低,所以先處理 parent 。

“公司開除程序猿,也是先開始作用較低。。”

重點(diǎn)其實(shí)在于 各式各樣的處理函數(shù) strat,下面將會(huì)一一列舉

2、defaultStrats

這段函數(shù)言簡意賅,意思就是優(yōu)先使用組件的options

組件options>組件 mixin options>全局options

var defaultStrats= function(parentVal, childVal) {        
    return childVal === undefined ?        
            parentVal :
            childVal
};
3、data

我們先默認(rèn) data 的值是一個(gè)函數(shù),簡化下源碼 ,但是其實(shí)看上去還是會(huì)有些復(fù)雜

不過我們主要了解他的工作過程就好了

1、兩個(gè)data函數(shù) 組裝成一個(gè)函數(shù)

2、合并 兩個(gè)data函數(shù)執(zhí)行返回的 數(shù)據(jù)對(duì)象

strats.data = function(parentVal, childVal, vm) {    

    return mergeDataOrFn(
        parentVal, childVal, vm
    )
};

function mergeDataOrFn(parentVal, childVal, vm) {    

    return function mergedInstanceDataFn() {        

        var childData = childVal.call(vm, vm) 

        var parentData = parentVal.call(vm, vm)        

        if (childData) {            

            return mergeData(childData, parentData)

        } else {            

            return parentData
        }
    }
}

function mergeData(to, from) {    

    if (!from) return to    

    var key, toVal, fromVal;    

    var keys = Object.keys(from);   

    for (var i = 0; i < keys.length; i++) {

        key = keys[i];
        toVal = to[key];

        fromVal = from[key];    

        // 如果不存在這個(gè)屬性,就重新設(shè)置
        if (!to.hasOwnProperty(key)) {
            set(to, key, fromVal);
        }      

        // 存在相同屬性,合并對(duì)象
        else if (typeof toVal =="object" && typeof fromVal =="object) {
            mergeData(toVal, fromVal);
        }
    }    
    return to
}
4、生命鉤子

把所有的鉤子函數(shù)保存進(jìn)數(shù)組,重要的是數(shù)組子項(xiàng)的順序

順序就是這樣

[    
    全局 mixin - created,
    組件 mixin-mixin - created,
    組件 mixin - created,
    組件 options - created
]

所以當(dāng)數(shù)組執(zhí)行的時(shí)候,正序遍歷,就會(huì)先執(zhí)行全局注冊(cè)的鉤子,最后是 組件的鉤子

function mergeHook(parentVal, childVal) {    

    var arr;

    arr = childVal ?  

        // concat 不只可以拼接數(shù)組,什么都可以拼接
        ( parentVal ?  
            // 為什么parentVal 是個(gè)數(shù)組呢

            // 因?yàn)闊o論怎么樣,第一個(gè) parent 都是{ component,filter,directive}
            // 所以在這里,合并的時(shí)候,肯定只有 childVal,然后就變成了數(shù)組
            parentVal.concat(childVal) : 

            ( Array.isArray(childVal) ? childVal: [childVal] )
        ) :
        parentVal  

    return arr

}

strats["created"] = mergeHook;
strats["mounted"] = mergeHook;
// ... 等其他鉤子
5、component、directives、filters

我一直覺得這個(gè)是比較好玩的,這種類型的合并方式,我是從來沒有在項(xiàng)目中使用過的

原型疊加

兩個(gè)對(duì)象并沒有進(jìn)行遍歷合并,而是把一個(gè)對(duì)象直接當(dāng)做另一個(gè)對(duì)象的原型

這種做法的好處,就是為了保留兩個(gè)相同的字段且能訪問,避免被覆蓋

學(xué)到了學(xué)到了.....反正我是學(xué)到了

strats.components=
strats.directives=

strats.filters = function mergeAssets(
    parentVal, childVal, vm, key
) {    
    var res = Object.create(parentVal || null);    

    if (childVal) { 
        for (var key in childVal) {
            res[key] = childVal[key];
        }   
    } 
    return res
}

就是下面這種,層層疊加的原型

6、watch

watch 的處理,也是合并成數(shù)組,重要的也是合并順序,跟 生命鉤子一樣

這樣的鉤子

[    
    全局 mixin - watch,
    組件 mixin-mixin - watch,
    組件 mixin - watch,
    組件 options - watch
]

按照正序執(zhí)行,最后執(zhí)行的 必然是組件的 watch

strats.watch = function(parentVal, childVal, vm, key) { 

    if (!childVal) {        
        return Object.create(parentVal || null)
    }    

    if (!parentVal)  return childVal

    var ret = {};    

    // 復(fù)制 parentVal 到 ret 中
    for (var key in parentVal) {
       ret[key] = parentVal[key];
    }    

    for (var key$1 in childVal) {        

        var parent = ret[key$1];        
        var child = childVal[key$1];        

        if (!Array.isArray(parent)) {
            parent = [parent];
        }
        ret[key$1] = parent ? parent.concat(child) : 
                ( Array.isArray(child) ? child: [child] );

    }    
    return ret
};
7、props、computed、methods

這幾個(gè)東西,是不允許重名的,合并成對(duì)象的時(shí)候,不是你死就是我活

重要的是,以誰的為主?必然是組件options 為主了

比如

組件的 props:{ name:""}

組件mixin 的 props:{ name:"", age: "" }

那么 把兩個(gè)對(duì)象合并,有相同屬性,組件的 name 會(huì)替換 mixin 的name

trats.props = 
strats.methods = 
strats.inject = 

strats.computed = function(parentVal, childVal, vm, key) {    

    if (!parentVal) return childVal

    var ret = Object.create(null);   


    // 把 parentVal 的字段 復(fù)制到 ret 中
    for (var key in parentVal) {
       ret[key] = parentVal[key];
    }    

    if (childVal) {        
        for (var key in childVal) {
           ret[key] = childVal[key];
        }
    }    

    return ret

};

其實(shí)在白話版里面,就已經(jīng)測(cè)試了很多例子,整個(gè)執(zhí)行的流程也描述很清楚了,這里就是放個(gè)源碼供參考

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

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

相關(guān)文章

  • Vue原理】Mixin - 白話

    摘要:而我覺得現(xiàn)在出一個(gè)白話版,是讓大家有興趣去研究源碼的時(shí)候,可以提前理清一下思路。相當(dāng)于封裝,提取公共部分。顯然,今天我不是來教大家怎么用的,怎么用看文檔就好了,我是講解生命的真諦內(nèi)部的工作原理。而這個(gè)不會(huì)合并,直接替換掉整個(gè)選項(xiàng) 寫文章不容易,點(diǎn)個(gè)贊唄兄弟專注 Vue 源碼分享,文章分為白話版和 源碼版,白話版助于理解工作原理,源碼版助于了解內(nèi)部詳情,讓我們一起學(xué)習(xí)吧研究基于 Vue版...

    CollinPeng 評(píng)論0 收藏0
  • Vue原理】生命周期 - 源碼

    摘要:其中的標(biāo)志位什么時(shí)候設(shè)置呢,是在相應(yīng)的鉤子觸發(fā)之后,具體看下面源碼怎么執(zhí)行鉤子呢沒錯(cuò),就是下面這個(gè)函數(shù)是自己傳入的等回調(diào)那是怎么用呢比如觸發(fā)就會(huì)這么調(diào)用很簡單不,直接拿到鉤子,然后遍歷執(zhí)行,綁定上下文對(duì)象。 寫文章不容易,點(diǎn)個(gè)贊唄兄弟專注 Vue 源碼分享,文章分為白話版和 源碼版,白話版助于理解工作原理,源碼版助于了解內(nèi)部詳情,讓我們一起學(xué)習(xí)吧研究基于 Vue版本 【2.5.17】 ...

    siberiawolf 評(píng)論0 收藏0
  • Vue原理】Component - 源碼 之 創(chuàng)建組件VNode

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

    hover_lew 評(píng)論0 收藏0
  • UI組件庫從1到N開發(fā)心得-組件篇

    摘要:正文距離第一篇組件庫文章發(fā)布已經(jīng)過去個(gè)月了,在此期間利用零零散散的時(shí)間持續(xù)更新組件庫,目前移動(dòng)端組件庫已經(jīng)更新大類基礎(chǔ)表單彈出層種組件供使用。鏈接組件庫從到開發(fā)心得主頁更改版版方案祝工作順利鄧文斌年月日正文 距離第一篇UI組件庫文章發(fā)布已經(jīng)過去3個(gè)月了,在此期間利用零零散散的時(shí)間持續(xù)更新owl-ui組件庫,目前owl-ui移動(dòng)端組件庫已經(jīng)更新3大類(基礎(chǔ)、表單、彈出層)9種組件(Button...

    hzc 評(píng)論0 收藏0
  • Vue全家桶+Mint-Ui打造高仿QQMusic,搭配詳細(xì)說明

    摘要:簡介最近有點(diǎn)小閑置,于是乎希望寫點(diǎn)東西,正好自己喜歡聽歌,便決定自己寫一個(gè)音樂的簡易版。核心文件則是在在這里使用統(tǒng)一管理頁面切換動(dòng)畫,歌曲播放狀態(tài),歌曲進(jìn)度等信息。所有對(duì)于歌曲的操作都通過來進(jìn)行全局管理,然后對(duì)相應(yīng)的變化做出全局改變。 Vue-QQMusic 簡介: 最近有點(diǎn)小閑置,于是乎希望寫點(diǎn)東西,正好自己喜歡聽歌,便決定自己寫一個(gè)QQ音樂的簡易版。順便進(jìn)一步加深下自己對(duì)移動(dòng)端的知...

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

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

0條評(píng)論

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