keep-alive原理
keep-alive是抽象组件,不渲染真实DOM,通过缓存VNode实现组件实例复用,避免重复创建销毁。
keep-alive抽象组件
JavaScript
const KeepAlive = {
name: 'keep-alive',
abstract: true, // 抽象组件,不渲染真实DOM
props: {
include: [String, RegExp, Array],
exclude: [String, RegExp, Array],
max: [String, Number]
},
created() {
this.cache = Object.create(null) // 缓存池
this.keys = [] // 缓存key列表
}
}
abstract: true 使keep-alive不产生真实DOM节点。
缓存机制实现
JavaScript
// render函数核心逻辑
render() {
const vnode = getFirstComponentChild(this.$slots.default)
const name = getComponentName(vnode.componentOptions)
// 匹配检查
if (name && !matches(name, this.include, this.exclude)) {
return vnode // 不缓存,直接返回
}
const key = vnode.key ?? name
const { cache, keys } = this
if (cache[key]) {
vnode.componentInstance = cache[key].componentInstance
remove(keys, key)
keys.push(key) // LRU: 移到末尾
} else {
cache[key] = vnode
keys.push(key)
// 超出max限制,删除最久未使用
if (this.max && keys.length > this.max) {
pruneCacheEntry(cache, keys[0], keys)
}
}
vnode.data.keepAlive = true
return vnode
}
使用LRU策略,超出max限制时删除最久未使用的缓存。
组件激活与停用
JavaScript
// 被keep-alive包裹的组件
{
activated() {
// 从缓存恢复时调用
},
deactivated() {
// 被缓存时调用
}
}
通过钩子区分首次创建和从缓存恢复。
缓存清理机制
JavaScript
function pruneCacheEntry(cache, key, keys) {
const cached = cache[key]
if (cached) {
cached.componentInstance.$destroy()
}
cache[key] = null
remove(keys, key)
}
清除缓存时调用组件实例的 $destroy 方法清理资源。
include/exclude匹配
JavaScript
function matches(pattern, include, exclude) {
if (include) {
if (typeof include === 'string') {
return pattern.includes(include)
}
return checkMatch(pattern, include)
}
if (exclude) {
if (typeof exclude === 'string') {
return !pattern.includes(exclude)
}
return !checkMatch(pattern, exclude)
}
return true
}
支持字符串、正则、数组三种匹配方式。
VNode复用过程
JavaScript
// 首次渲染
<keep-alive>
<comp-a /> // 创建组件实例,缓存VNode
</keep-alive>
// 切换后
<keep-alive>
<comp-b /> // 创建新实例,缓存VNode,A被缓存
</keep-alive>
// 再次切回
<keep-alive>
<comp-a /> // 从缓存恢复,复用组件实例
</keep-alive>
VNode缓存包含完整的组件实例引用,恢复时直接复用。
要点总结
- keep-alive是抽象组件(
abstract: true),不渲染真实DOM - 通过
cache对象和keys数组实现LRU缓存策略 - 缓存的是包含组件实例引用的VNode
- 支持
include/exclude/max三种配置 activated/deactivated钩子区分首次创建和缓存恢复- 清除缓存时调用
$destroy清理组件资源
📝 发现内容有误?点击此处直接编辑