Vue3 的 KeepAlive 组件 include/exclude 匹配算法与缓存淘汰机制
字数 1429 2025-12-15 09:18:28
Vue3 的 KeepAlive 组件 include/exclude 匹配算法与缓存淘汰机制
描述:
Vue3 的 <KeepAlive> 组件可以缓存动态组件的实例,避免重复渲染。其 include 和 exclude 属性用于控制哪些组件需要缓存或排除缓存,内部基于组件的 name 选项进行匹配。同时,缓存系统采用 LRU(最近最少使用)策略管理缓存容量,确保内存不会无限增长。这里重点讲解匹配算法的实现细节与缓存淘汰机制的原理。
解题过程循序渐进讲解:
步骤 1:缓存数据结构设计
KeepAlive 内部维护一个缓存对象(Map)和一个键的数组(数组模拟 LRU 队列)。
// 简化表示
const cache = new Map() // 键 -> 组件实例
const keys = [] // 键的顺序数组,尾部为最近使用
- 键(key):由组件的虚拟节点(vnode)的
type和key属性组合生成,确保唯一性。 - 值(value):组件的实例(vnode.component)。
keys数组记录键的访问顺序,用于实现 LRU 淘汰。
步骤 2:include/exclude 匹配算法
匹配发生在组件被激活(activated)或卸载(deactivated)时。
- 获取组件的
name:从组件选项(vnode.type.name)或组件实例的name属性获取。 - 标准化
include和exclude:它们可以是字符串、正则表达式或数组,编译时会被统一为数组形式。 - 匹配逻辑:
- 如果
include存在,检查name是否在include列表中 → 不在则直接返回,不缓存。 - 如果
exclude存在,检查name是否在exclude列表中 → 在则直接返回,不缓存。
- 如果
- 匹配方法:内部使用
matches函数,支持字符串(如"ComponentA")和正则表达式(如/^Async/)的匹配。
步骤 3:缓存淘汰机制(LRU 实现)
KeepAlive 通过 max 属性设置最大缓存数,默认无限制。
- 当缓存新实例时,将键添加到
keys尾部。 - 访问已缓存实例时,将对应键移动到
keys尾部(标记为最近使用)。 - 当缓存数量超过
max时,触发淘汰:- 移除
keys头部的键(最久未使用)。 - 从
cache中删除对应实例,并调用该实例的unmounted钩子进行清理。
- 移除
步骤 4:生命周期与缓存状态同步
缓存的组件实例不会触发普通的 unmounted,而是触发 deactivated 钩子(失活)。激活时触发 activated 钩子。
- 缓存实例时:从原容器移动到隐藏的容器(
storageContainer的div元素),DOM 被隐藏而非销毁。 - 激活实例时:从隐藏容器移回实际容器。
步骤 5:键的生成与更新
键基于组件的 type 和 key 生成。如果用户为动态组件绑定 key,缓存会以 key 为区分(例如同一组件不同数据视为不同缓存)。无 key 时则用组件类型标识,可能导致相同类型组件被覆盖缓存。
总结:
KeepAlive 通过 include/exclude 的 name 匹配算法筛选缓存目标,通过 LRU 队列(keys 数组 + max 限制)管理缓存容量,结合 DOM 移动而非销毁的机制实现组件实例的高效复用。