keep-alive是 Vue 内置的一个组件,可以使被包含的组件保留状态,或避免重新渲染。
首先介绍下Vue的渲染过程:
Vue的渲染是从render阶段开始的,而keep-alive的渲染是从vnode->patch阶段(构建虚拟DOM数并将虚拟DOM转换为真正的DOM节点的过程)的。
export default {
name: 'keep-alive',
abstract: true,
props: {
include: patternTypes,/*字符串或正则表达式。只有名称匹配的组件会被缓存*/
exclude: patternTypes,/*字符串或正则表达式。任何名称匹配的组件都不会被缓存。*/
max: [String, Number],/*数字。最多可以缓存多少组件实例。*/
},
created(){...},
destroyed(){...},
mounted(){...},
render(){
//获取默认插槽中的第一个组件节点
const slot = this.$slots.default
const vnode: VNode = getFirstComponentChild(slot)
//获取该组件节点的componentOptions
const componentOptions: ?VNodeComponentOptions = vnode && vnode.componentOptions
/*如果组件节点存在,获取该节点的名称,取值优先为组件name,如若不存在name则取tag。判断该节点名称在不在include||在exclude,就直接返回vnode*/
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
}
/*end*/
/*重点*/
const { cache, keys } = this
const key: ?string = vnode.key == null //获取组件key值
// same constructor may get registered as different local components
// so cid alone is not enough (#3269)
? componentOptions.Ctor.cid + (componentOptions.tag ? `::${componentOptions.tag}` : '')
: vnode.key
//如果存在缓存,直接从缓存中取vnode实例
if (cache[key]) {
vnode.componentInstance = cache[key].componentInstance
//将其删除并添加在最后
remove(keys, key)
keys.push(key)
} else {
//如果不存在缓存,则对组件进行缓存
cache[key] = vnode
keys.push(key)
// 如果配置了max并且超过max,则从缓存中删除第一个
if (this.max && keys.length > parseInt(this.max)) {
pruneCacheEntry(cache, keys[0], keys, this._vnode)
}
}
//最后设置keepAlive
vnode.data.keepAlive = true
}
return vnode || (slot && slot[0])
}
}
在这里可以看出了keep-alive是名为keep-alive的组件,定义了一个abstract属性并赋值为true,这是为了定义它是一个抽象组件,它自身不会渲染一个 DOM 元素,也不会出现在组件的父组件链中。props属性:
include- 字符串或正则表达式。只有名称匹配的组件会被缓存。exclude- 字符串或正则表达式。任何名称匹配的组件都不会被缓存。max- 数字。最多可以缓存多少组件实例。