<keep-alive> 是 Vue 提供的内置组件,用于缓存包裹的组件实例,避免组件频繁创建和销毁带来的性能开销。它不会渲染成真实 DOM,仅作为一个 “容器” 管理内部组件的缓存状态。
一、基本用法
通过包裹动态组件(component 标签)或路由组件(router-view),实现组件缓存:
1. 缓存动态组件
vue
<template>
<div>
<button @click="currentComponent = 'ComponentA'">显示A</button>
<button @click="currentComponent = 'ComponentB'">显示B</button>
<!-- 缓存包裹的组件 -->
<keep-alive>
<component :is="currentComponent"></component>
</keep-alive>
</div>
</template>
<script>
import ComponentA from './ComponentA.vue'
import ComponentB from './ComponentB.vue'
export default {
components: { ComponentA, ComponentB },
data() {
return {
currentComponent: 'ComponentA'
}
}
}
</script>
- 切换组件时,被缓存的组件不会触发
beforeDestroy、destroyed等销毁钩子,再次显示时也不会重新触发created、mounted等初始化钩子。
2. 缓存路由组件
在路由切换场景中(如标签页),缓存页面组件:
vue
<!-- App.vue 中 -->
<template>
<div>
<router-link to="/home">首页</router-link>
<router-link to="/about">关于</router-link>
<!-- 缓存路由组件 -->
<keep-alive>
<router-view></router-view>
</keep-alive>
</div>
</template>
- 路由切换时,被缓存的页面组件状态会保留(如表单输入内容、滚动位置等)。
二、核心属性
<keep-alive> 提供 3 个属性控制缓存范围:
| 属性 | 类型 | 说明 |
|---|---|---|
include | 字符串 / 正则 | 仅缓存名称匹配的组件(需匹配组件的 name 选项) |
exclude | 字符串 / 正则 | 不缓存名称匹配的组件(优先级高于 include) |
max | 数字 / 字符串 | 最多缓存的组件实例数量,超出时销毁最早缓存的实例(避免内存占用过高) |
1. include 与 exclude(匹配组件名称)
需确保组件定义了 name 选项(单文件组件默认以文件名作为 name,但显式定义更可靠):
vue
<!-- 组件 A(ComponentA.vue) -->
<script>
export default {
name: 'ComponentA' // 必须定义 name 才能被 include/exclude 匹配
}
</script>
使用示例:
vue
<!-- 仅缓存 ComponentA 和 ComponentB -->
<keep-alive include="ComponentA,ComponentB">
<component :is="currentComponent"></component>
</keep-alive>
<!-- 不缓存 ComponentC -->
<keep-alive exclude="ComponentC">
<router-view></router-view>
</keep-alive>
<!-- 正则匹配(需用 v-bind) -->
<keep-alive :include="/Component[A|B]/">
<component :is="currentComponent"></component>
</keep-alive>
2. max 限制缓存数量
vue
<!-- 最多缓存 3 个组件实例 -->
<keep-alive max="3">
<router-view></router-view>
</keep-alive>
- 当缓存的组件实例超过 3 个时,最早被缓存的实例会被销毁(触发
deactivated钩子)。
三、缓存组件的生命周期钩子
被 <keep-alive> 缓存的组件,会新增两个专属钩子:
| 钩子 | 触发时机 | 用途示例 |
|---|---|---|
activated | 组件从缓存中被激活(显示)时触发 | 刷新数据、重置定时器等 |
deactivated | 组件被缓存(隐藏)时触发 | 清除定时器、保存临时状态等 |
示例:
vue
<!-- 缓存的组件中 -->
<script>
export default {
activated() {
// 组件显示时执行(如重新请求数据)
this.fetchData()
this.timer = setInterval(() => {}, 1000)
},
deactivated() {
// 组件隐藏时执行(如清除定时器)
clearInterval(this.timer)
},
// 注意:created/mounted 仅在组件首次创建时执行一次
mounted() {
console.log('仅执行一次')
}
}
</script>
四、结合路由的高级用法
实际开发中,常需要 “按需缓存路由组件”(部分页面缓存,部分不缓存),可通过 路由元信息(meta) 实现:
1. 路由配置中标记是否需要缓存
js
// router/index.js
const routes = [
{
path: '/home',
component: Home,
meta: { keepAlive: true } // 需要缓存
},
{
path: '/about',
component: About,
meta: { keepAlive: false } // 不需要缓存
}
]
2. 在 router-view 中根据元信息动态控制
vue
<template>
<!-- 动态决定是否缓存当前路由组件 -->
<keep-alive>
<router-view v-if="$route.meta.keepAlive"></router-view>
</keep-alive>
<router-view v-if="!$route.meta.keepAlive"></router-view>
</template>
五、注意事项
-
仅缓存组件实例,不缓存 DOM
<keep-alive>缓存的是组件实例(数据和状态),DOM 会被复用,但不会 “冻结” DOM 状态(如v-show控制的显示状态会被保留,因为依赖数据)。 -
不支持缓存函数式组件
函数式组件没有实例,无法被缓存,需改用状态式组件。 -
避免过度缓存
缓存过多组件会占用内存,尤其是包含大量数据的组件,建议结合max属性限制数量。 -
Vue3 中的变化
Vue3 中<keep-alive>的用法与 Vue2 一致,但需注意:- 组件的
name选项在<script setup>中需显式定义(defineOptions({ name: 'XXX' }))。 - 配合
<Suspense>使用时,缓存逻辑会作用于异步组件的加载状态。
- 组件的
总结
<keep-alive> 是优化组件切换性能的关键工具,核心价值在于保留组件状态、减少重复渲染。实际使用时需结合 include/exclude 精准控制缓存范围,通过 activated/deactivated 处理缓存前后的逻辑,并注意避免无差别缓存导致的内存问题。
6785

被折叠的 条评论
为什么被折叠?



