{ Ctor: Ctor, propsData: propsData, listeners: listeners, tag: tag, children: children },
asyncFactory
);
return vnode
}
Vue最后都会通过patch函数进行渲染,将vnode转换成真实的dom,对于组件则会通过createComponent进行渲染
function createComponent (vnode, insertedVnodeQueue, parentElm, refElm) {
var i = vnode.data;
if (isDef(i)) {
var isReactivated = isDef(vnode.componentInstance) && i.keepAlive;
if (isDef(i = i.hook) && isDef(i = i.init)) {
i(vnode, false /* hydrating */);
}
// after calling the init hook, if the vnode is a child component
// it should've created a child instance and mounted it. the child
// component also has set the placeholder vnode's elm.
// in that case we can just return the element and be done.
if (isDef(vnode.componentInstance)) {
initComponent(vnode, insertedVnodeQueue);
insert(parentElm, vnode.elm, refElm);
if (isTrue(isReactivated)) {
reactivateComponent(vnode, insertedVnodeQueue, parentElm, refElm);
}
return true
}
}
}
接下去分两步介绍
keep-alive组件本身的渲染
keep-alive包裹组件的渲染,本例中的Foo组件和Bar组件
先讲讲本例中针对keep-alive组件本身的渲染
根组件实例化
根组件$mount
根组件调用mountComponent
根组件生成renderWatcher
根组件调用updateComponent
根组件调用vm.render()生成根组件vnode
根组件调用vm.update(vnode)
根组件调用vm.patch(oldVnode, vnode)
根组件调用createElm(vnode)
在children渲染的时候,如果遇到组件类型的vnode则调用createComponent(vnode),而正是在这个过程中,进行了子组件的实例化及挂载($mount)
所以在执行createElm(keepAliveVnode)的过程中会对keep-alive组件的实例化及挂载,而在实例化的过程中,keep-alive包裹的子组件的vnode会赋值给keep-alive组件实例的$slot属性,所以在keep-alive实例调用render函数时,可以通过this.$slot拿到包裹组件的vnode,在demo中,就是Foo组件的vnode,具体分析下keep-alive组件的render函数
render () {
const slot = this.$slots.default
const vnode: VNode = getFirstComponentChild(slot)
const componentOptions: ?VNodeComponentOptions = vnode && vnode.componentOptions
if (componentOptions) {
const name: ?string = getComponentName(componentOptions)
const { include, exclude } = this
if (
// not included
(include && (!name || !matches(include, name))) ||
// excluded
(exclude && name && matches(exclude, name))
) {
return vnode
} const { cache, keys } = this










