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

資訊專欄INFORMATION COLUMN

人人都能懂的Vue源碼系列—06—mergeOptions-下

megatron / 1035人閱讀

摘要:下面分別為大家介紹鉤子函數(shù)的策略所有關(guān)于鉤子函數(shù)的策略,其實(shí)都是調(diào)用方法。的策略介紹完了鉤子函數(shù)的合并策略,我們接下來看等屬性的合并策略。如果當(dāng)前實(shí)例或者構(gòu)造函數(shù)上有一個沒有屬性,則返回另一個的屬性,如果兩者都有,則同樣調(diào)用方法處理合并。

上篇文章,我們講到了mergeOptions的部分實(shí)現(xiàn),今天接著前面的部分講解,來看代碼,如果大家覺得看講解枯燥可以直接翻到本文的最后看mergeOptions的整個流程圖。

  const extendsFrom = child.extends
  if (extendsFrom) {
    parent = mergeOptions(parent, extendsFrom, vm)
  }
  if (child.mixins) {
    for (let i = 0, l = child.mixins.length; i < l; i++) {
      parent = mergeOptions(parent, child.mixins[i], vm)
    }
  }

這段代碼的處理的邏輯是,當(dāng)傳入的options里有mixin或者extends屬性時,再次調(diào)用mergeOptions方法合并mixins和extends里的內(nèi)容到實(shí)例的構(gòu)造函數(shù)options上(即parent options)比如下面這種情況

 const childComponent = Vue.component("child", {
      ...
      mixins: [myMixin],
      extends: myComponent
      ...
 })
 const myMixin = {
      created: function () {
        this.hello()
      },
      methods: {
        hello: function () {
          console.log("hello from mixin")
      }
    }
  }
 const myComponent = {
      mounted: function () {
        this.goodbye()
      },
      methods: {
        goodbye: function () {
          console.log("goodbye from mixin")
        }
     }
  }

就會把傳入的mounted, created鉤子處理函數(shù),還有methods方法提出來去和parent options做合并處理。
弄明白了這點(diǎn)我們繼續(xù)回到mergeOptions的代碼

const options = {}
let key

變量options存儲合并之后的options,變量key存儲parent options和child options上的key值。
接下來的部分算是mergeOptions方法的核心處理部分了,像炒菜一樣,前面的代碼相當(dāng)于把所有的菜都配好了。接下來的部分就是教你怎么去炒菜了。

  for (key in parent) {
    mergeField(key)
  }
  for (key in child) {
    if (!hasOwn(parent, key)) {
      mergeField(key)
    }
  }
  function mergeField (key) {
    const strat = strats[key] || defaultStrat
    options[key] = strat(parent[key], child[key], vm, key)
  }

前兩段for循環(huán)代碼大同小異,都是遍歷options上的key值,然后調(diào)用mergeField方法來處理options。mergeField方法中出現(xiàn)了一個變量strats和defaultStrat。這兩個變量存儲的就是我們的合并策略,也就是炒菜的菜譜,我們先來看看defaultStrat

const defaultStrat = function (parentVal: any, childVal: any): any {
  return childVal === undefined
    ? parentVal
    : childVal
}

defaultStrat的邏輯是,如果child上該屬性值存在時,就取child上的該屬性值,如果不存在,則取parent上的該屬性值。現(xiàn)在我們知道默認(rèn)的合并策略是什么了,接下來看其他的合并策略。我們來看看strats里都有哪些屬性?

上圖就是strats中所有的策略了。粗略看起來里面的內(nèi)容非常的多,如果細(xì)細(xì)分析會發(fā)現(xiàn),其實(shí)總結(jié)起來無非就是幾種合并策略。下面分別為大家介紹

鉤子函數(shù)的策略

所有關(guān)于鉤子函數(shù)的策略,其實(shí)都是調(diào)用mergeHook方法。

function mergeHook (
  parentVal: ?Array,
  childVal: ?Function | ?Array
): ?Array {
  return childVal
    ? parentVal
      ? parentVal.concat(childVal)
      : Array.isArray(childVal)
        ? childVal
        : [childVal]
    : parentVal
}

mergeHook采用了一個非常騷的嵌套三元表達(dá)式來控制最后的返回值。下面我們來解析這段三元表達(dá)式
(1) child options上不存在該屬性,parent options上存在,則返回parent上的屬性。

(2)child和parent都存在該屬性,則返回concat之后的屬性

(3)child上存在該屬性,parent不存在,且child上的該屬性是Array,則直接返回child上的該屬性

(4) child上存在該屬性,parent不存在,且child上的該屬性不是Array,則把該屬性先轉(zhuǎn)換成Array,再返回。


上面就是鉤子函數(shù)合并策略,結(jié)合圖片看應(yīng)該會比較清晰。

props/methods/inject/computed的策略

介紹完了鉤子函數(shù)的合并策略,我們接下來看props,methods,inject,computed等屬性的合并策略。

strats.props =
strats.methods =
strats.inject =
strats.computed = function (
  parentVal: ?Object,
  childVal: ?Object,
  vm?: Component,
  key: string
): ?Object {
  if (childVal && process.env.NODE_ENV !== "production") {
    assertObjectType(key, childVal, vm)
  }
  if (!parentVal) return childVal
  const ret = Object.create(null)
  extend(ret, parentVal)
  if (childVal) extend(ret, childVal)
  return ret
}

這個合并方法邏輯很簡單,如果child options上這些屬性存在,則先判斷它們是不是對象。
(1)如果parent options上沒有該屬性,則直接返回child options上的該屬性
(2)如果parent options和child options都有,則合并parent options和child options并生成一個新的對象。(如果parent和child上有同名屬性,合并后的以child options上的為準(zhǔn))

components/directives/filters的合并策略

components/directives/filters這幾個屬性的處理邏輯如下

function mergeAssets (
  parentVal: ?Object,
  childVal: ?Object,
  vm?: Component,
  key: string
): Object {
  const res = Object.create(parentVal || null)
  if (childVal) {
    process.env.NODE_ENV !== "production" && assertObjectType(key, childVal, vm)
    return extend(res, childVal)
  } else {
    return res
  }
}

這里的處理邏輯和上一種情況的類似,這里不做過多講解。

data和provide的策略

data和provide的策略相對來說復(fù)雜一些,我們先來看代碼

export function mergeDataOrFn (
  parentVal: any,
  childVal: any,
  vm?: Component
): ?Function {
  if (!vm) {
    // in a Vue.extend merge, both should be functions
    if (!childVal) {
      return parentVal
    }
    if (!parentVal) {
      return childVal
    }
    // when parentVal & childVal are both present,
    // we need to return a function that returns the
    // merged result of both functions... no need to
    // check if parentVal is a function here because
    // it has to be a function to pass previous merges.
    return function mergedDataFn () {
      return mergeData(
        typeof childVal === "function" ? childVal.call(this, this) : childVal,
        typeof parentVal === "function" ? parentVal.call(this, this) : parentVal
      )
    }
  } else {
    return function mergedInstanceDataFn () {
      // instance merge
      const instanceData = typeof childVal === "function"
        ? childVal.call(vm, vm)
        : childVal
      const defaultData = typeof parentVal === "function"
        ? parentVal.call(vm, vm)
        : parentVal
      if (instanceData) {
        return mergeData(instanceData, defaultData)
      } else {
        return defaultData
      }
    }
  }
}

這個合并策略可以分成兩種情況來考慮。
第一種情況,當(dāng)前調(diào)用mergeOptions操作的是vm實(shí)例(調(diào)用new新建vue實(shí)例觸發(fā)mergeOptions方法)

   return function mergedInstanceDataFn () {
      // instance merge
      const instanceData = typeof childVal === "function"
        ? childVal.call(vm, vm)
        : childVal
      const defaultData = typeof parentVal === "function"
        ? parentVal.call(vm, vm)
        : parentVal
      if (instanceData) {
        return mergeData(instanceData, defaultData)
      } else {
        return defaultData
      }
    }

如果新建實(shí)例時傳入的options上有data屬性,則調(diào)用mergeData方法合并實(shí)例上的data屬性和其構(gòu)造函數(shù)options上的data屬性(如果有的話)
第二種情況,當(dāng)前調(diào)用mergeOptions操作的不是vm實(shí)例(即通過Vue.extend/Vue.component調(diào)用了mergeOptions方法)

 if (!vm) {
    // in a Vue.extend merge, both should be functions
    if (!childVal) {
      return parentVal
    }
    if (!parentVal) {
      return childVal
    }
    // when parentVal & childVal are both present,
    // we need to return a function that returns the
    // merged result of both functions... no need to
    // check if parentVal is a function here because
    // it has to be a function to pass previous merges.
    return function mergedDataFn () {
      return mergeData(
        typeof childVal === "function" ? childVal.call(this, this) : childVal,
        typeof parentVal === "function" ? parentVal.call(this, this) : parentVal
      )
    }
  }

在這種情況下,其處理邏輯也是類似的。如果當(dāng)前實(shí)例options或者構(gòu)造函數(shù)options上有一個沒有data屬性,則返回另一個的data屬性,如果兩者都有,則同樣調(diào)用mergeData方法處理合并。
既然這兩種情況都調(diào)用了mergeData方法,那我們就繼續(xù)來看看mergeData的源碼

function mergeData (to: Object, from: ?Object): Object {
  if (!from) return to
  let key, toVal, fromVal
  const keys = Object.keys(from)
  for (let i = 0; i < keys.length; i++) {
    key = keys[i]
    toVal = to[key]
    fromVal = from[key]
    if (!hasOwn(to, key)) {
      set(to, key, fromVal)
    } else if (isPlainObject(toVal) && isPlainObject(fromVal)) {
      mergeData(toVal, fromVal)
    }
  }
  return to
}

mergeData的邏輯是,如果from對象中有to對象里沒有的屬性,則調(diào)用set方法,(這里的set就是Vue.$set,先可以簡單理解為對象設(shè)置屬性。之后會細(xì)講)如果from和to中有相同的key值,且key對應(yīng)的value是對象,則會遞歸調(diào)用mergeData方法,否則以to的值為準(zhǔn),最后返回to對象。這里我們就講完了data的合并策略。
返回mergeOptions代碼里,在經(jīng)過這幾種合并策略合并options后,最終返回options

return options
總結(jié)

講到這里,整個mergeOptions的流程也講完了。這個方法牽扯到的內(nèi)容比較多,流程也比較復(fù)雜。為了大家更好的理解和記憶。我畫了一張圖來表達(dá)整個mergeOptions的過程。

如果大家覺得我的文章寫的還行,請為我點(diǎn)贊,你們的認(rèn)可是我最大的動力。

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

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

相關(guān)文章

  • 人人都能懂的Vue源碼系列—05—mergeOptions-上

    摘要:在解析完其構(gòu)造函數(shù)上的之后,需要把構(gòu)造函數(shù)上的和實(shí)例化時傳入的進(jìn)行合并操作并生成一個新的。檢查組件名稱是否合法首先看傳入的三個參數(shù),,這三個參數(shù)分別代表的是該實(shí)例構(gòu)造函數(shù)上的實(shí)例化時傳入的實(shí)例本身。 前幾篇文章中我們講到了resolveConstructorOptions,它的主要功能是解析當(dāng)前實(shí)例構(gòu)造函數(shù)上的options,不太明白的同學(xué)們可以看本系列的前幾篇文章。在解析完其構(gòu)造函數(shù)...

    iKcamp 評論0 收藏0
  • 人人都能懂的Vue源碼系列—04—resolveConstructorOptions函數(shù)-

    摘要:上一篇文章中說道,函數(shù)要分兩種情況進(jìn)行說明,第一種是為基礎(chǔ)構(gòu)造器的情況,這個已經(jīng)向大家介紹過了,今天這篇文章主要介紹第二種情況,是創(chuàng)建的子類。表示的是當(dāng)前構(gòu)造器上新增的,表示的是當(dāng)前構(gòu)造器上新增的封裝。 上一篇文章中說道,resolveConstructorOptions函數(shù)要分兩種情況進(jìn)行說明,第一種是Ctor為基礎(chǔ)構(gòu)造器的情況,這個已經(jīng)向大家介紹過了,今天這篇文章主要介紹第二種情況...

    My_Oh_My 評論0 收藏0
  • 人人都能懂的Vue源碼系列—04—resolveConstructorOptions函數(shù)-

    摘要:上一篇文章中說道,函數(shù)要分兩種情況進(jìn)行說明,第一種是為基礎(chǔ)構(gòu)造器的情況,這個已經(jīng)向大家介紹過了,今天這篇文章主要介紹第二種情況,是創(chuàng)建的子類。表示的是當(dāng)前構(gòu)造器上新增的,表示的是當(dāng)前構(gòu)造器上新增的封裝。 上一篇文章中說道,resolveConstructorOptions函數(shù)要分兩種情況進(jìn)行說明,第一種是Ctor為基礎(chǔ)構(gòu)造器的情況,這個已經(jīng)向大家介紹過了,今天這篇文章主要介紹第二種情況...

    BlackHole1 評論0 收藏0
  • 人人都能懂的Vue源碼系列—02—Vue構(gòu)造函數(shù)

    摘要:果然我們找到了的構(gòu)造函數(shù)定義。告訴你是一個構(gòu)造函數(shù),需要用操作符去調(diào)用。在深入方法之前,我們先把目光移到文件里在的構(gòu)造函數(shù)定義之后,有一系列方法會被立即調(diào)用。下篇博文主要介紹相關(guān)的內(nèi)容,涉及到原型鏈和構(gòu)造函數(shù)以及部分的實(shí)現(xiàn),敬請期待 上篇博文中說到了Vue源碼的目錄結(jié)構(gòu)是什么樣的,每個目錄的作用我們應(yīng)該也有所了解。我們知道core/instance目錄主要是用來實(shí)例化Vue對象,所以我...

    X_AirDu 評論0 收藏0
  • 人人都能懂的Vue源碼系列—03—resolveConstructorOptions函數(shù)-上

    摘要:上篇文章介紹了構(gòu)造函數(shù)的部分實(shí)現(xiàn),當(dāng)前實(shí)例不是組件時,會執(zhí)行方法。這個文件就是對構(gòu)造函數(shù)進(jìn)行的第一層包裝了。但是注意這里的代碼我們構(gòu)造函數(shù)的第二層包裝,就在這個文件里了。回到的源碼中,當(dāng)不存在時,直接返回基礎(chǔ)構(gòu)造器的。 上篇文章介紹了Vue構(gòu)造函數(shù)的部分實(shí)現(xiàn),當(dāng)前Vue實(shí)例不是組件時,會執(zhí)行mergeOptions方法。 vm.$options = mergeOptions( re...

    snifes 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<