
import Vue from 'vue'
import App from './App.vue
var app = new Vue({
el: 'app',
render(h) {
return h(App)
}
})
我们这里的tag是一个组件对象,所以vnode是通过createComponent()生成,方法的定义是在/vdom/createComponent.js/文件中定义的

Ctor可以是一个组件类型的类,或者是函数或对象,data是vnode相关的data,context是当前的vm实例,children是组件子vnode等等

首先baseCtor取得是vm上$options._base

这个options._base我们在全局初始化的时候就赋值为Vue

在init的时候有一个合并options的操作,所以他会把Vue.options合并到vm.$options,所以我们这里通过context.options._base就访问到了vm.$options._base,所以这里baseCtor就是Vue

后面判断传入的Ctor是一个对象的话就会调用Vue.extend()去把这个对象转换成新的构造器

Vue.extend传入一个对象,返回一个构造函数,里面Super指向自己Vue,拿到superId,cachedCtors实际上是一个缓存的优化,然后拿到组件name extendOptions.name,会在开发环境对这个组件name做一层校验

如果不满足就会报警告Invalid component name:XXX. Component names should conform to valid custom element...。如果传入的组件name是一个内置的html标签有冲突的情况下会报警告Do not use built-in or reserved HTML elements as component

回到extend方法,接下来定义了一个子构造函数,也是调用了this._init()方法。把子构造函数原型指向父构造的原型,然后把子构造函数原型的构造指向自身。Sub.options把父构造的options和自身做了一个合并,接下来对自身的props和computed做了初始化。后面就是给Sub赋值一些属性和方法,目的就是为了和vue有一样的能力

最后赋值给cachedCtors[SuperId]缓存起来,

多个组件引用一个组件的时候,构造器逻辑创建只会执行一次,下次走进来的时候发现,传入的是同一个对象,已经定义过并且有值了,SuperId是一样的话说明他们是基于同一个父构造器继承而来的,直接把缓存的构造器返回就行了,不用再创建

回到createComponent方法,接下来判断Ctor不是一个函数的话就会报警告Invalid Component definition...
接下来是一个异步组件的处理,现在先跳过

然后对data做处理并重新计算options,因为可能会被全局的mixins影响,对v-model的一些判断,对props的一些处理以及对函数组件的一些处理

接下来是对自定义事件的一些处理。以上可以跳过

installComponentHooks(data)安装一些组件的钩子,之前在patch过程中讲过,在不同的patch会执行不同的钩子create insert destory...等等



installComponentHooks里面遍历了hooksToMerge,实际上是遍历拿到componentVNodeHooks里面四个钩子函数合并到hooks

最后生成一个vnode返回,这个vnode和我们之前的不一样,有一个前缀标识vue-component-....当我们调试看见vnode有一个这样的标识,就知道是一个组件。
比较核心的几点:
1.Ctor构造器的生成是继承Vue的
2.组件vnode的data都会有一些hook,这些hook会merge到自身组件的hooks上
3.生成组件vnode和之前的不一样,没有children(以后插槽会用到)多了一些标识和options
本文解析Vue组件创建过程,包括Ctor的继承机制、vNode数据处理与hooks整合,以及组件vNode的独特标识。重点讲解了构造器生成、组件钩子和vNode的区别。
945

被折叠的 条评论
为什么被折叠?



