# vue源码 keep-alive
# 初次渲染
- 不会重复渲染相同的组件,只会利用初次渲染保留的缓存去更新节点
- 当路由切换的时候,被包裹的组件不会被销毁,重新进入时不会重新创建实例,会从缓存里面读取
keep-alive
的Vnode会剔除多余的属性内容,由于它在其他属性在组件内部并没有意义,例如class样式
# keep-alive
- vue在组件实例创建的时候会根据abstract属性决定是否忽略某个组件
- keep-alive : abstract:true, vue跳过了它
export default {
name: 'keep-alive',
abstract: true,
props: {
include: patternTypes,
exclude: patternTypes,
max: [String, Number]
},
methods: {
cacheVNode() {
const { cache, keys, vnodeToCache, keyToCache } = this
if (vnodeToCache) {
const { tag, componentInstance, componentOptions } = vnodeToCache
cache[keyToCache] = {
name: getComponentName(componentOptions),
tag,
componentInstance,
}
keys.push(keyToCache)
// prune oldest entry
if (this.max && keys.length > parseInt(this.max)) {
pruneCacheEntry(cache, keys[0], keys, this._vnode)
}
this.vnodeToCache = null
}
}
},
created () {
this.cache = Object.create(null) //缓存对象
this.keys = []//里面保存 vnode.componentInstance = cache[key].componentInstance
},
# createComponent
- /vdom/create-component.js
export function createComponent{
...
if (isTrue(Ctor.options.abstract)) {
// 只保留slot属性,其他标签属性都被移除,在vnode对象上不再存在
const slot = data.slot
data = {}
if (slot) {
data.slot = slot
}
}
}
patch
执行阶段会调用createElm
创建真实dom
,在创建节点途中,keep-alive
的vnode
对象会被认定是一个组件Vnode
,因此针对组件Vnode
又会执行createComponent
函数,它会对keep-alive
组件进行初始化和实例化
# createComponent
- patch.js
isReactivated
用来判断组件是否缓存- 首次:vnode.componentInstance 空,keepalive:true,走创建vnode
- 第二次,已经缓存,把上一次的dom插入即可
function createComponent (vnode, insertedVnodeQueue, parentElm, refElm) {
var i = vnode.data
if (isDef(i)) {
// isReactivated用来判断组件是否缓存。
var isReactivated = isDef(vnode.componentInstance) && i.keepAlive;
if (isDef(i = i.hook) && isDef(i = i.init)) {
// 执行组件初始化的内部钩子 init
i(vnode, false /* hydrating */);
}
if (isDef(vnode.componentInstance)) {
// 其中一个作用是保留真实dom到vnode中
initComponent(vnode, insertedVnodeQueue);
insert(parentElm, vnode.elm, refElm);
if (isTrue(isReactivated)) {
reactivateComponent(vnode, insertedVnodeQueue, parentElm, refElm);
}
return true
}
}
}
# 想局部刷新怎么办
- beforeRouteEnter --> created --> mounted --> activated --> deactivated
- 用钩子
activated