# keep-alive 组件的原理
# 含义
keep-alive组件是一个抽象组件,它自身不会渲染成DOM元素,也不会出现在父组件链中。
# props 参数
include: 定义缓存的白名单exclude: 定义缓存的黑名单max: 定义缓存组件的数量上限值,超出将移除较久没使用的(LRU的策略)
# 部分源码解析
abstract属性控制是否渲染成DOM元素cache: 用来作为缓存容器,保存vnode节点keys:存放已缓存的组件名(每次缓存组件被访问(或者新访问一个组件),就会把访问的放到尾部,这样比较少用的就在头部,结合max属性,把头部的优先移除掉)
// src/core/components/keep-alive.js
export default {
name: 'keep-alive',
abstract: true, // 判断当前组件虚拟dom是否渲染成真实dom的关键
props: {
include: patternTypes, // 缓存白名单
exclude: patternTypes, // 缓存黑名单
max: [String, Number] // 缓存的组件
},
created() {
this.cache = Object.create(null) // 缓存虚拟dom
this.keys = [] // 缓存的虚拟dom的键集合
},
/* destroyed钩子中销毁所有cache中的组件实例 */
destroyed() {
for (const key in this.cache) {
// 删除所有的缓存
pruneCacheEntry(this.cache, key, this.keys)
}
},
mounted() {
// 实时监听黑白名单的变动
this.$watch('include', val => {
pruneCache(this, name => matched(val, name))
})
this.$watch('exclude', val => {
pruneCache(this, name => !matches(val, name))
})
},
render() {
/* 得到slot插槽中的第一个组件 */
const vnode: VNode = getFirstComponentChild(this.$slots.default)
const componentOptions: ?VNodeComponentOptions = vnode && vnode.componentOptions
if (componentOptions) {
}
return vnode
}
}
# destroyed 生命周期
- 不是简单的
this.cache=null, 而是遍历销毁所有的缓存组件 - 内部会调用
vm.$destroy(), 完全的销毁一个实例,清理它与其他实例的连接,解绑它的全部指令和事件监听器。 - 会触发各个缓存组件的
beforeDestroy和destroyed的钩子。
# 被缓存组件的生命周期
第一次渲染就是 正常的生命周期,然后多一个
activated和deactivated钩子函数。保存的是 VNode
通过 cache对象保存
render方法通过 $slots.default 来缓存对应的vnode虚拟Dom节点