Vue3缓存组件keep-alive
一、keep-alive
核心概念
作用:keep-alive
是 Vue3 的内置组件,用于缓存动态组件或路由组件实例,避免重复渲染带来的性能损耗。当组件被包裹时,会保留其状态(如数据、DOM 结构、滚动位置等),直到达到缓存上限或手动清理。
生命周期变化:
被缓存的组件新增两个特殊生命周期:
onActivated
:组件被激活时触发(首次加载或从缓存恢复)onDeactivated
:组件被缓存时触发
常规的unmounted
只会在组件被永久销毁时执行。
二、基础使用场景与示例
1. 动态组件缓存
场景:切换标签页时保留表单输入状态
<template>
<button @click="currentTab = 'FormA'">表单A</button>
<button @click="currentTab = 'FormB'">表单B</button>
<keep-alive>
<component :is="currentTab"></component>
</keep-alive>
</template>
<script setup>
import { ref } from 'vue';
import FormA from './FormA.vue';
import FormB from './FormB.vue';
const currentTab = ref('FormA');
</script>
此时切换标签,输入框内容不会重置。
2. 路由级缓存
场景:SPA 应用中保留页面状态
<!-- App.vue -->
<template>
<router-view v-slot="{ Component }">
<keep-alive :include="['Home', 'Profile']">
<component :is="Component" />
</keep-alive>
</router-view>
</template>
// router.js
{
path: '/home',
name: 'Home',
component: () => import('./views/Home.vue'),
meta: { keepAlive: true } // 可选元信息控制
}
通过 include
指定需缓存的组件名(需与组件 name
选项一致)。
三、高级配置技巧
1. 缓存策略控制
通过三个属性实现精准控制:
include
:字符串/正则/数组,匹配需缓存的组件名exclude
:排除不需要缓存的组件max
:最大缓存数,超限时按 LRU 算法淘汰
示例:
<keep-alive :max="5" include="['Dashboard', /^Chart/]">
<router-view />
</keep-alive>
该配置会缓存:
- 名为
Dashboard
的组件 - 名称以
Chart
开头的组件 - 最多保留 5 个实例
2. 状态刷新管理
问题:缓存导致数据不更新
解决方案:
<script setup>
import { onActivated } from 'vue';
onActivated(() => {
fetchData(); // 每次激活时刷新数据
});
</script>
结合 onDeactivated
可清理定时器等副作用。
四、实战场景与解决方案
案例 1:列表页-详情页状态保留
需求:返回列表页时保留滚动位置和筛选条件
// router.js
const router = createRouter({
scrollBehavior(to, from, savedPosition) {
if (savedPosition) return savedPosition;
if (from.meta.keepAlive) {
return { top: from.meta.scrollTop || 0 };
}
return { top: 0 };
}
});
在列表页组件中记录滚动位置:
<script setup>
import { onDeactivated } from 'vue';
onDeactivated(() => {
route.meta.scrollTop = document.documentElement.scrollTop;
});
</script>
案例 2:解决定时器干扰
问题:组件缓存后定时器仍在运行
方案:在 deactivated
中清理
<script setup>
import { onActivated, onDeactivated } from 'vue';
let timer = null;
onActivated(() => {
timer = setInterval(updateData, 5000);
});
onDeactivated(() => {
clearInterval(timer);
});
</script>
五、原理深度解析
缓存机制:
- 内部维护
cache
(Map 对象)存储组件实例 - 使用
keys
(Set 对象)记录访问顺序 - 通过
pruneCacheEntry
淘汰旧实例
- 内部维护
DOM 处理:
激活时通过move
方法将缓存的 DOM 重新插入文档流,而非重新渲染LRU 算法:
当达到max
限制时,淘汰最久未访问的组件实例
六、最佳实践与注意事项
命名规范:
始终为可缓存组件设置name
选项,确保include/exclude
生效内存监控:
避免无限制缓存,建议结合max
和业务逻辑手动清理(可通过访问__v_cache
实现)组合式 API:
推荐使用<script setup>
配合生命周期钩子,逻辑更清晰调试技巧:
通过 Vue Devtools 的 "Components > KeepAlive" 面板查看缓存状态
完整示例项目结构
src/
├── components/
│ ├── FormA.vue
│ └── FormB.vue
├── views/
│ ├── Home.vue
│ └── Profile.vue
├── router.js
└── App.vue
通过上述配置,可实现多级路由缓存与状态管理。
本文综合了 Vue3 官方文档核心思想与最佳实践方案,如需更深入的实现细节,可参考 Vue 源码中的 runtime-core/src/components/KeepAlive.ts
模块。