Vue.js源碼分析(六)--component vnode

Ctor

前面講vnode生成都是通過判斷tag是否爲string類型時的過程,當我們使用組件時情況就不一樣了,這裏主要是通過createComponent方法實現的。
在這裏插入圖片描述
首先照常先看函數簽名,由以下五個:

  Ctor: Class<Component> | Function | Object | void,
  data: ?VNodeData,
  context: Component,
  children: ?Array<VNode>,
  tag?: string

首先是一個傳入的tag,不是字符串,而是一個構造函數,data即VNodeData, context即vm實例,首先要把vm.$options._base賦值給新的變量:

  const baseCtor = context.$options._base

這裏baseCtor即爲Vue,下一步就是調用Vue.extend方法,轉到Vue.extend之中,裏面第一個重要邏輯就是對所謂的tag進行校驗

    const name = extendOptions.name || Super.options.name
    if (process.env.NODE_ENV !== 'production' && name) {
      validateComponentName(name)
    }

這裏也會看到常見的錯誤:

  if (!new RegExp(`^[a-zA-Z][\\-\\.0-9_${unicodeRegExp.source}]*$`).test(name)) {
    warn(
      'Invalid component name: "' + name + '". Component names ' +
      'should conform to valid custom element name in html5 specification.'
    )
  }
  if (isBuiltInTag(name) || config.isReservedTag(name)) {
    warn(
      'Do not use built-in or reserved HTML elements as component ' +
      'id: ' + name
    )
  }

再接着會創建一個子的構造函數去繼承原構造函數,並進行初始化等操作優化,最後返回的也是子類構造函數;同時也做了一層緩存,節約了多次調用createComponent時不必要的消耗,通過這兩種方式返回新的構造器。

接着讓我們再返回createCompoent。

createCompoent

通過剛剛的操作我們拿到了新的構造器,之後會有一些v-model,異步組件之類的邏輯,我們先忽略,直到走到 installComponentHooks, 這裏是用來掛載組件的一些鉤子函數。

最後我們會調用:

  const vnode = new VNode(
    `vue-component-${Ctor.cid}${name ? `-${name}` : ""}`,
    data,
    undefined,
    undefined,
    undefined,
    context,
    { Ctor, propsData, listeners, tag, children },
    asyncFactory
  );

這裏對照vnode的構造函數的實現,我們可以發現一些端倪,首先就是children,element,text都是undefined的,這個原因也會後面講到,接着還會傳遞一個componentOptions,在這個裏面反而傳遞了children,tag等東西。

最後返回vnode即可。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章