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

資訊專欄INFORMATION COLUMN

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

iKcamp / 2698人閱讀

摘要:在解析完其構(gòu)造函數(shù)上的之后,需要把構(gòu)造函數(shù)上的和實(shí)例化時(shí)傳入的進(jìn)行合并操作并生成一個(gè)新的。檢查組件名稱是否合法首先看傳入的三個(gè)參數(shù),,這三個(gè)參數(shù)分別代表的是該實(shí)例構(gòu)造函數(shù)上的實(shí)例化時(shí)傳入的實(shí)例本身。

前幾篇文章中我們講到了resolveConstructorOptions,它的主要功能是解析當(dāng)前實(shí)例構(gòu)造函數(shù)上的options,不太明白的同學(xué)們可以看本系列的前幾篇文章。在解析完其構(gòu)造函數(shù)上的options之后,需要把構(gòu)造函數(shù)上的options和實(shí)例化時(shí)傳入的options進(jìn)行合并操作并生成一個(gè)新的options。這個(gè)合并操作就是今天要講的mergeOptions。如果大家不想看枯燥的講解,可以直接點(diǎn)擊人人都能懂的Vue源碼系列—04—mergeOptions-下,翻到文章最后,查看整個(gè)mergeOptions的流程圖。

Merge two option objects into a new one.
Core utility used in both instantiation and inheritance.

先來(lái)看源碼中對(duì)mergeOptions方法的注釋。mergeOptions的功能是合并兩個(gè)options對(duì)象,并生成一個(gè)新的對(duì)象。是實(shí)例化和繼承中使用的核心方法。可見mergeOptions方法的重要性。既然這么重要,那我就帶大家一行一行的來(lái)解析代碼。保證大家看完這篇文章后,能徹底的理解mergeOptions的作用。

export function mergeOptions (
  parent: Object,
  child: Object,
  vm?: Component
): Object {
  if (process.env.NODE_ENV !== "production") {
    checkComponents(child) // 檢查組件名稱是否合法
  }

  if (typeof child === "function") {
    child = child.options
  }

  normalizeProps(child, vm)
  normalizeInject(child, vm)
  normalizeDirectives(child)
  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)
    }
  }
  const options = {}
  let key
  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)
  }
  return options
}

首先看傳入的三個(gè)參數(shù),parent,child,vm,這三個(gè)參數(shù)分別代表的是該實(shí)例構(gòu)造函數(shù)上的options,實(shí)例化時(shí)傳入的options,vm實(shí)例本身。結(jié)合Vue作者寫的注釋,我們明白了,原來(lái)mergeoptions方法是要合并構(gòu)造函數(shù)和傳入的options這兩個(gè)對(duì)象。
明白了這點(diǎn)之后,接下來(lái)往下看

if (process.env.NODE_ENV !== "production") {
    checkComponents(child) // 檢查組件名稱是否合法
 }

這段代碼主要是判斷當(dāng)前環(huán)境是不是生產(chǎn)環(huán)境,如果不是,則調(diào)用checkComponents方法來(lái)檢查組件名稱是否是可用名稱。我們來(lái)看看checkComponents的邏輯。

function checkComponents (options: Object) {
  for (const key in options.components) {
    validateComponentName(key)
  }
}
export function validateComponentName (name: string) {
  if (!/^[a-zA-Z][w-]*$/.test(name)) {
    warn(
      "Invalid component name: "" + name + "". Component names " +
      "can only contain alphanumeric characters and the hyphen, " +
      "and must start with a letter."
    )
  }
  if (isBuiltInTag(name) || config.isReservedTag(name)) {
    warn(
      "Do not use built-in or reserved HTML elements as component " +
      "id: " + name
    )
  }
}

如果child的options(實(shí)例化傳入的options)有components屬性。如下面這種情況

const app = new Vue({
   el: "#app",
   ...
   components: {
     childComponent
   }
   ...
})

那么就調(diào)用validateComponentName來(lái)驗(yàn)證傳入的組件名稱是否符合以下特征。

包含數(shù)字,字母,下劃線,連接符,并且以字母開頭

是否和html標(biāo)簽名稱或svg標(biāo)簽名稱相同

是否和關(guān)鍵字名稱相同,如undefined, infinity等

如果滿足第一條,并且第2,3條都是不相同的話,那么組件名稱可用。
我們?cè)倩氐絤ergeOptions源碼中

if (typeof child === "function") {
    child = child.options
}

如果child是function類型的話,我們?nèi)∑鋙ptions屬性作為child。
接下來(lái)看這三個(gè)方法以normalize開頭的方法

normalizeProps(child, vm)
normalizeInject(child, vm)
normalizeDirectives(child)

這三個(gè)方法的功能類似,分別是把options中的props,inject,directives屬性轉(zhuǎn)換成對(duì)象的形式。因?yàn)橛行﹤魅氲臅r(shí)候可能會(huì)是數(shù)組的形式。如

Vue.component("blog-post", {
  props: ["postTitle"],
  template: "

{{ postTitle }}

" })
normalizeProps

我們先來(lái)看props處理的邏輯

function normalizeProps (options: Object, vm: ?Component) {
  const props = options.props
  if (!props) return
  const res = {}
  let i, val, name
  if (Array.isArray(props)) {
    i = props.length
    while (i--) {
      val = props[i]
      if (typeof val === "string") {
        name = camelize(val)
        res[name] = { type: null }
      } else if (process.env.NODE_ENV !== "production") {
        warn("props must be strings when using array syntax.")
      }
    }
  } else if (isPlainObject(props)) {
    for (const key in props) {
      val = props[key]
      name = camelize(key)
      res[name] = isPlainObject(val)
        ? val
        : { type: val }
    }
  } else if (process.env.NODE_ENV !== "production") {
    warn(
      `Invalid value for option "props": expected an Array or an Object, ` +
      `but got ${toRawType(props)}.`,
      vm
    )
  }
  options.props = res
}

首先明確這兩個(gè)方法里的參數(shù)是什么,options傳入的是child,即實(shí)例化時(shí)傳入的options。vm是實(shí)例。知道了這兩個(gè)參數(shù)是什么,我們繼續(xù)來(lái)研究代碼。

const props = options.props
if (!props) return
const res = {}
let i, val, name

上面的代碼主要是聲明一些變量。res用來(lái)存放修改后的props,最后把res賦給新的props。下面的邏輯可以分為兩種情況來(lái)考慮

props是數(shù)組

當(dāng)props是數(shù)組的時(shí)候,如下面這種情況

Vue.component("blog-post", {
  props: ["postTitle"],
  template: "

{{ postTitle }}

" })

它的處理邏輯是,遍歷props數(shù)組,把數(shù)組的每一項(xiàng)的值作為res對(duì)象的key,value值等于{type: null},即把上面例子中的["postTitle"]轉(zhuǎn)換成下面這種形式

{
  postTitle: { type: null }
}
props是對(duì)象

當(dāng)props是對(duì)象時(shí),如下面這種情況

Vue.component("my-component", {
  props: {
    // 必填的字符串
    propC: {
      type: String,
      required: true
    }
  }
})

這種情況的處理邏輯是遍歷對(duì)象,先把對(duì)象的key值轉(zhuǎn)換成駝峰的形式。然后再判斷對(duì)象的值,如果是純對(duì)象(即調(diào)用object.prototype.toString方法的結(jié)果是[object Object]),則直接把對(duì)象的值賦值給res,如果不是,則把{ type: 對(duì)象的值}賦給res。最終上面這種形式會(huì)轉(zhuǎn)換成

{
  propC: {
   type: String,
   required: true
  }
}

如果傳入的props不是純對(duì)象也不是數(shù)組,且當(dāng)前環(huán)境也不是生產(chǎn)環(huán)境,則拋出警告。

warn(
  `Invalid value for option "props": expected an Array or an Object, ` +
  `but got ${toRawType(props)}.`,
   vm
)

最后,把處理過(guò)的props重新賦值給options.props。

normalizeInject

這個(gè)方法的邏輯和normalizeProps類似,主要是處理inject。inject屬性如果大家平時(shí)不是寫庫(kù)或者插件的話,可能很少接觸到,可以先查看inject的使用,inject的傳入和props類似。可以傳入object,也可以傳入array

// array
var Child = {
  inject: ["foo"],
  created () {
    console.log(this.foo) // => "bar"
  }
  // ...
}
// object
const Child = {
  inject: {
    foo: {
      from: "bar",
      default: "foo"
    }
  }
}

由于這個(gè)方法和normalizeProps邏輯基本一樣,這里也不具體展開講了。上面的demo最終會(huì)被轉(zhuǎn)換成如下形式

// array
{
  foo: { from: "foo"}
}
// object
{
 foo: {
   from: "bar",
   default: "foo"
 }
}
normalizeDirectives

這個(gè)方法主要是處理一些自定義指令,如果不了解自定義指令的同學(xué)可以自定義指令。這里的方法處理邏輯主要針對(duì)自定義指令中函數(shù)簡(jiǎn)寫的情況。如下

Vue.directive("color", function (el, binding) {
  el.style.backgroundColor = binding.value
})

normalizeDirectives構(gòu)造函數(shù)會(huì)把這個(gè)指令傳入的參數(shù),最終轉(zhuǎn)換成下面這種形式

  color: {
    bind: function (el, binding) {
      el.style.backgroundColor = binding.value
    },
    update: function (el, binding) {
      el.style.backgroundColor = binding.value
    }
  }

由于文章篇幅所限,本篇文章先講解到這里,下篇繼續(xù)帶大家來(lái)看mergeOptions的實(shí)現(xiàn)。

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

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

相關(guān)文章

  • 人人都能懂的Vue源碼系列—04—resolveConstructorOptions函數(shù)-下

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

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

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

    BlackHole1 評(píng)論0 收藏0
  • 人人都能懂的Vue源碼系列—06—mergeOptions-下

    摘要:下面分別為大家介紹鉤子函數(shù)的策略所有關(guān)于鉤子函數(shù)的策略,其實(shí)都是調(diào)用方法。的策略介紹完了鉤子函數(shù)的合并策略,我們接下來(lái)看等屬性的合并策略。如果當(dāng)前實(shí)例或者構(gòu)造函數(shù)上有一個(gè)沒有屬性,則返回另一個(gè)的屬性,如果兩者都有,則同樣調(diào)用方法處理合并。 上篇文章,我們講到了mergeOptions的部分實(shí)現(xiàn),今天接著前面的部分講解,來(lái)看代碼,如果大家覺得看講解枯燥可以直接翻到本文的最后看mergeO...

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

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

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

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

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

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

0條評(píng)論

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