vue2.x源码解析六——组件化--2.createComponent虚拟DOM组件

本文详细解析Vue2.x中组件化的实现过程,重点分析`createComponent`方法。首先介绍组件初始化的背景,然后探讨`createComponent`如何构造子类构造函数,包括Vue.extend的功能和子类构造函数的创建。接着讲解安装组件钩子函数的过程,最后阐述实例化VNode的步骤。文章深入浅出地揭示了Vue组件化的核心原理。
摘要由CSDN通过智能技术生成

1.说明

我们以Vue-cli 初始化的代码为例,来分析一下 Vue 组件初始化的一个过程。

import Vue from 'vue'
import App from './App.vue'

var app = new Vue({
  el: '#app',
  // 这里的 h 是 createElement 方法
  render: h => h(App)
})

和我们上一章相同的点也是通过 render 函数去渲染的,不同的这次通过 createElement 传的参数是一个组件而不是一个原生的标签。

2.接上一章

上一章我们在分析虚拟DOM的实现

过程是 init –> $mount(挂载) –> render(参生虚拟DOM) –> path (映射真实DOM)

render(参生虚拟DOM) 是调用 createElement 的实现的时候,它最终会调用 _createElement 方法,其中有一段逻辑是对参数 tag 的判断,如果是一个普通的 html 标签,像上一章的例子那样是一个普通的 div,则会实例化一个普通 VNode 节点,否则通过 createComponent 方法创建一个组件 VNode。
scr/core/vnode/create-elements.js

if (typeof tag === 'string') {
  let Ctor
  ns = (context.$vnode && context.$vnode.ns) || config.getTagNamespace(tag)
  if (config.isReservedTag(tag)) {
    // platform built-in elements
    vnode = new VNode(
      config.parsePlatformTagName(tag), data, children,
      undefined, undefined, context
    )
  } else if (isDef(Ctor = resolveAsset(context.$options, 'components', tag))) {
    // component
    vnode = createComponent(Ctor, data, context, children, tag)
  } else {
    // unknown or unlisted namespaced elements
    // check at runtime because it may get assigned a namespace when its
    // parent normalizes children
    vnode = new VNode(
      tag, data, children,
      undefined, undefined, context
    )
  }
} else {
  // direct component options / constructor
  vnode = createComponent(tag, data, context, children)
}

在我们这一章传入的是一个 App 对象,它本质上是一个 Component 类型,那么它会走到上述代码的 else 逻辑,直接通过 createComponent 方法来创建 vnode。所以接下来我们来看一下 createComponent 方法的实现,它定义在 src/core/vdom/create-component.js 。

3.createComponent 方法

src/core/vdom/create-component.js中:

export function createComponent (
 //可以是组件类型的类,函数或者对象 
  Ctor: Class<Component> | Function | Object | void,
  // VNode(虚拟DOM)的相关Data
  data: ?VNodeData,
  // 上下文,也就是我们的当前的Vue实例---vm
  context: Component,
  // 组件的子VNode
  children: ?Array<VNode>,
  tag?: string
): VNode | Array<VNode> | void {
  if (isUndef(Ctor)) {
    return
  }


  const baseCtor = context.$options._base

  // plain options object: turn it into a constructor
  if (isObject(Ctor)) {
    Ctor = baseCtor.extend(Ctor)
  }

  // if at this stage it's not a constructor or an async component factory,
  // reject.
  if (typeof Ctor !== 'function') {
    if (process.env.NODE_ENV !== 'production') {
      warn(`Invalid Component definition: ${String(Ctor)}`, context)
    }
    return
  }

  // async component
  let asyncFactory
  if (isUndef(Ctor.cid)) {
    asyncFactory = Ctor
    Ctor = resolveAsyncComponent(asyncFactory, baseCtor, context)
    if (Ctor === undefined) {
      // return a plac
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值