13.2 从模板编译到生成vnode
按照以往分析的经验,我们会从模板的解析开始说起,第一个疑问便是:内置组件和普通组件在编译过程有区别吗?答案是没有的,不管是内置的还是用户定义组件,本质上组件在模板编译成render
函数的处理方式是一致的,这里的细节不展开分析,有疑惑的可以参考前几节的原理分析。最终针对keep-alive
的render
函数的结果如下:
with(this){···_c('keep-alive',{attrs:{"include":"child2"}},[_c(chooseTabs,{tag:"component"})],1)}
有了render
函数,接下来从子开始到父会执行生成Vnode
对象的过程,_c('keep-alive'···)
的处理,会执行createElement
生成组件Vnode
,其中由于keep-alive
是组件,所以会调用createComponent
函数去创建子组件Vnode
,createComponent
之前也有分析过,这个环节和创建普通组件Vnode
不同之处在于,keep-alive
的Vnode
会剔除多余的属性内容,由于keep-alive
除了slot
属性之外,其他属性在组件内部并没有意义,例如class
样式,<keep-alive clas="test"></keep-alive>
等,所以在Vnode
层剔除掉多余的属性是有意义的。而<keep-alive slot="test">
的写法在2.6以上的版本也已经被废弃。(其中abstract
作为抽象组件的标志,以及其作用我们后面会讲到)
// 创建子组件Vnode过程
function createComponent(Ctordata,context,children,tag) {
// abstract是内置组件(抽象组件)的标志
if (isTrue(Ctor.options.abstract)) {
// 只保留slot属性,其他标签属性都被移除,在vnode对象上不再存在
var slot = data.slot;
data = {};
if (slot) {
data.slot = slot;
}
}
}