【Vue2.x 源码学习】第三十九篇 - 组件部分 - 创建组件虚拟节点
一,前言
上篇,介绍了组件部分-组件的合并,主要涉及以下几个点:
组件初始化情况;
组件合并的位置;
组件合并的策略;
组件合并后测试;
本篇,组件部分-组件的编译;
二,前文回顾
通过 Vue.component 全局 API 声明全局组件;
Vue.component 内部使用 Vue.extend 生成组件的构造函数;
将组件构造函数维护到全局对象
Vue.options.components
中备用;在 new Vue 初始化时,在 mergeOptions 方法中,使用策略模式找到组件的合并策略,完成全局组件和局部组件的合并操作;
至此,在 vm.$options
中,就已经完成了组件关系的构建;
组件查找规则:优先查找局部组件,找不到继续在链上查找全局组件;
回顾模板解析流程:
第一步,将 html 模板生成 AST 语法树;
第二步,根据 AST 语法树生成 render 函数;
第三步,在 render 函数中,调用 _c(即 createElement 方法)处理标签,生成元素标签的虚拟节点 vnode;
三,组件的编译流程
以上边组件为例,组件的编译过程与模板相似:
- 第一步,根据组件 html 模板生成 AST 语法树;
- 第二步,根据 AST 语法树生成 render 函数;
- 第三步,在 render 函数中,调用 _c 处理组件,生成组件的虚拟节点 componentVnode;
组件与标签编译的区别:
- 标签需要生成标签的虚拟节点;
- 组件需要生成组件的虚拟节点;
因此,可对原 createElement 方法进行扩展,使之支持组件的编译,生成组件的虚拟节点;
四,生成组件虚拟节点
1,扩展 createElement 方法
原 createElement 方法:生成标签元素的虚拟节点 vnode:
现在,由于组件的加入,createElement 方法中 tag 不一定是元素,还可能是组件;
log 打印输出 2 次:
第一次:my-button(组件)
第二次:div(标签)
因此,需要对 createElement 方法进行扩展:添加 tag 为组件时的处理逻辑,创建对应组件的虚拟节点componentVnode
;
2,区分组件 or 元素
判断依据:tag 是否属于原始/普通标签:
如果 tag 属于原始标签,说明 tag 是元素,如:div;
如果 tag 不属于原始标签,说明 tag 是组件, 如:my-button;
3,createComponent 方法定义
获取对应组件的构造函数,并创建组件虚拟节点:
通过 vm.$options.components 获取对应组件的构造函数;
通过 createComponent 方法创建组件的虚拟节点;
注意 Ctor 的取值:
会先到
vm.$options.components
对象上查找局部组件,如果找到了 Ctor 会是一个对象;(因为局部组件定义不会被Vue.extend
处理成为组件构造函数)如果没找到,会继续到链上找全局组件,此时的
Ctor
会是一个函数;(因为全局组件内部会调用Vue.extend
处理成为组件构造函数)
所以,在createComponent
中,当Ctor
为对象时,需要先通过Vue.extend
处理为组件的构造函数;
4,createComponent 方法实现
扩展 vnode 结构
首先,需要扩展 vnode 结构,添加组件选项 componentOptions:
如何获取到 Vue.extend
为了便于后续使用 Vue.extend,在初始化时,将 Vue 保存到
Vue.options._base
;
当组件初始化时,会将 Vue.options 和组件的 options 进行合并,在这个过程中 _base 也将被合并到组件的 options 上;
这样一来,所有的 vm.$options 就都能够取到 _base 即 Vue 了;
所以,所有的组件都要通过 Vue.extend 方法,生成组件的构造函数:
全局组件:在 Vue.component 内部就被 Vue.extend 处理;
局部组件:在 createComponent 创建组件虚拟节点时,被 Vue.extend 处理;
扩展组件选项 componentOptions
组件没有孩子,“组件的孩子”就是插槽,所以 children 应放入
componentOptions
组件选项中;当是组件是,data 数据也属于组件,同样也需要放入
componentOptions
组件选项中...完整的 componentOptions 应包括:Ctor、propsData、listeners、tag、children;
5,测试组件虚拟节点生成
componentVnode 即为组件的虚拟节点;
其中,componentOptions 选项中包含组件的构造函数 Ctor;
四,结尾
本篇,介绍了组件部分-组件的编译,主要涉及以下几部分:
组件编译流程介绍:
html->render->vnode
创建组件虚拟节点:
createComponent
下一篇,组件部分-组件的生命周期;
评论