vue keepalive 实现原理
Vue KeepAlive 实现原理
Vue 的 KeepAlive 是一个内置组件,用于缓存不活动的组件实例,避免重复渲染和销毁。其核心原理基于组件的生命周期钩子和虚拟 DOM 的缓存机制。
缓存机制
KeepAlive 通过维护一个缓存对象(cache)来存储被缓存的组件实例。当组件切换时,KeepAlive 会检查缓存中是否存在该组件的实例。如果存在,则直接复用;否则,创建新的实例并缓存。
缓存的键(key)默认由组件的 name 选项生成,如果没有 name,则根据组件的 tag 和上下文生成唯一标识。

生命周期钩子
KeepAlive 利用了 Vue 组件的生命周期钩子来实现激活和停用逻辑:
- 被缓存的组件会触发
deactivated钩子,而不是destroyed。 - 当组件从缓存中重新激活时,会触发
activated钩子。
虚拟 DOM 复用
KeepAlive 通过 vnode(虚拟节点)的缓存和复用机制,避免重复渲染。当组件被缓存时,其对应的 vnode 和 DOM 节点会被保留;重新激活时,直接复用缓存的 vnode,跳过渲染流程。

LRU 缓存策略
默认情况下,KeepAlive 使用 LRU(最近最少使用)策略管理缓存。通过 max 属性可以设置缓存的最大数量,超出时自动销毁最久未使用的实例。
实现示例
以下是简化版的 KeepAlive 核心逻辑:
const KeepAlive = {
name: 'KeepAlive',
abstract: true, // 抽象组件,不渲染真实 DOM
props: {
include: [String, RegExp, Array],
exclude: [String, RegExp, Array],
max: [Number, String]
},
created() {
this.cache = Object.create(null) // 缓存对象
this.keys = [] // 缓存键的 LRU 队列
},
render() {
const slot = this.$slots.default
const vnode = slot[0] // 获取子组件 vnode
if (vnode) {
const key = vnode.key == null
? vnode.componentOptions.Ctor.cid + (vnode.componentOptions.tag ? `::${vnode.componentOptions.tag}` : '')
: vnode.key
if (this.cache[key]) {
vnode.componentInstance = this.cache[key].componentInstance // 复用实例
} else {
this.cache[key] = vnode // 缓存新实例
this.keys.push(key)
if (this.max && this.keys.length > parseInt(this.max)) {
pruneCacheEntry(this.cache, this.keys[0], this.keys) // LRU 淘汰
}
}
vnode.data.keepAlive = true // 标记为 keepAlive
}
return vnode
}
}
关键点总结
abstract: true标记为抽象组件,不参与真实 DOM 渲染。- 通过
vnode的componentInstance直接复用缓存的组件实例。 activated和deactivated钩子由KeepAlive内部逻辑触发。- LRU 策略通过
keys数组和max属性实现缓存淘汰。






