keep-alive
- 如果需要让已渲染组件重新创建可以通过删除keep-alive内的cache执行12this.$vnode.parent.componentInstance.$destroy()this.$vnode.parent.componentInstance.cache
keep-alive组件
- abstract组件不渲染,只处理内部的$slot
|
|
###
- 建立父子关系. 对keep-alive而言,parent的children没有自己, 但自己的parent还是parent.
|
|
首次渲染
- patch根节点到keep-alive组件,init的时候createComponentInstanceForVnode->new VueComponent
- keep-alive $mount $render接入render函数, 返回包裹的内容的vnode, update该vnode
- 内容vnode的vm实例的parent是keep-alive的父元素(如上面代码)
- 根节点patch结束之前调用
invokeInsertHook
, 会调用activateChildComponent
触发activated回调12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970function init (vnode, hydrating) {if (vnode.componentInstance &&!vnode.componentInstance._isDestroyed &&vnode.data.keepAlive) {// kept-alive components, treat as a patchvar mountedNode = vnode; // work around flowcomponentVNodeHooks.prepatch(mountedNode, mountedNode);} else {var child = vnode.componentInstance = createComponentInstanceForVnode(vnode,activeInstance);child.$mount(hydrating ? vnode.elm : undefined, hydrating);}}function render(){var slot = this.$slots.default;var vnode = getFirstComponentChild(slot);var componentOptions = vnode && vnode.componentOptions;if (componentOptions) {var ref = this;if (cache[key]) {vnode.componentInstance = cache[key].componentInstance;// make current key freshestremove(keys, key);keys.push(key);} else {cache[key] = vnode;keys.push(key);}vnode.data.keepAlive = true;}return vnode || (slot && slot[0])}// call invokeInsertHookfunction insert (vnode) {var context = vnode.context;var componentInstance = vnode.componentInstance;if (!componentInstance._isMounted) {componentInstance._isMounted = true;callHook(componentInstance, 'mounted');}if (vnode.data.keepAlive) {if (context._isMounted) {// vue-router#1212// During updates, a kept-alive component's child components may// change, so directly walking the tree here may call activated hooks// on incorrect children. Instead we push them into a queue which will// be processed after the whole patch process ended.queueActivatedComponent(componentInstance);} else {activateChildComponent(componentInstance, true /* direct */);}}}function activateChildComponent (vm, direct) {if (vm._inactive || vm._inactive === null) {vm._inactive = false;for (var i = 0; i < vm.$children.length; i++) {activateChildComponent(vm.$children[i]);}callHook(vm, 'activated');}}
二次渲染
- patchVnode到keep-alive组件时调用prepatch触发keep-alive组件重新渲染
- 重新渲染的vnode从缓存获取componentInstance
- 再次到createComponent 会执行init hook,就会跳过渲染vnode的vm创建
- 执行
initComponent
insert
后就完成dom插入 - keep-alive组件的patch最后执行invokeInsertHook, 执行在
initComponent
添加的包裹vnode的inserthook - 与首次渲染不同是activated回调通过先添加到
activatedChildren
中,再渲染完成后一并执行. 因为子组件在update的时候可能会变.
|
|
|
|
|
|
|
|
deactivated钩子
|
|