← 返回题目列表

Vue keep-alive 有什么作用?缓存策略和生命周期是什么?

高频 中等 第 12 / 27 题 更新于 2026/07/29
Vuekeep-alive缓存生命周期

简化版

keep-alive 用来缓存动态组件或路由组件实例,切换时不销毁组件,从而保留状态并减少重复渲染。它常用 includeexcludemax 控制缓存范围,并会触发 activateddeactivated 这类缓存相关生命周期。

详细版

典型用法:

<KeepAlive :max="10">
  <component :is="currentView" />
</KeepAlive>

路由场景常和 router-view 配合:

<RouterView v-slot="{ Component }">
  <KeepAlive>
    <component :is="Component" />
  </KeepAlive>
</RouterView>

keep-alive 适合列表页返回保留滚动位置、Tab 切换保留表单状态等场景。不适合缓存所有页面,否则内存会增长,还可能保留过期数据。

完整版教学

一、keep-alive 解决组件反复销毁重建的问题

默认情况下,动态组件或路由组件切走后会被卸载。 再次进入时,组件会重新创建,状态、滚动位置、未提交输入都可能丢失。 keep-alive 的作用是把组件实例缓存起来。

不使用 keep-alive:
  列表页创建 -> 进入详情页销毁 -> 返回列表页重新创建
使用 keep-alive:
  列表页创建 -> 进入详情页失活缓存 -> 返回列表页重新激活

如果列表页每次请求需要 500ms,用户来回 5 次就会明显感觉卡。 缓存后可以减少重复初始化,但也要承担内存占用和数据新鲜度问题。

二、它缓存的是组件实例,不只是 DOM

keep-alive 缓存的核心是组件实例。 组件的响应式状态、计算属性缓存、部分 DOM 状态都会保留下来。 所以返回页面时,不会像首次进入那样重新执行完整挂载流程。

<KeepAlive>
  <UserList v-if="showList" />
</KeepAlive>

这意味着列表页中的 page=3、筛选条件、展开行状态都可能被保留。 但接口数据是否过期,需要业务自己判断。 缓存不是数据同步方案,它只是保留组件实例。

三、include、exclude、max 控制缓存边界

include 表示只缓存匹配的组件,exclude 表示排除匹配的组件,max 表示最多缓存多少个实例。 这些配置通常依赖组件的 name。 如果组件没有稳定 name,匹配可能失效。

<KeepAlive include="UserList,OrderList" :max="10">
  <component :is="currentView" />
</KeepAlive>
配置作用常见用途
include只缓存命中的组件只缓存列表页
exclude不缓存命中的组件排除详情页、编辑页
max限制缓存数量防止内存无限增长

如果 max=10,第 11 个组件进入缓存时,最久未使用的缓存实例会被移除。 这类似 LRU 思路,能避免缓存越堆越多。

四、activated 和 deactivated 是缓存场景关键生命周期

keep-alive 缓存的组件切走时,不会走普通卸载逻辑。 它会进入失活状态,触发 deactivated。 再次显示时触发 activated

onActivated(() => {
  console.log('从缓存中恢复');
});

onDeactivated(() => {
  console.log('进入缓存');
});

这些钩子适合恢复滚动位置、刷新轻量数据、暂停定时器。 例如图表页面进入缓存时暂停轮询,恢复时再继续。 如果仍把所有清理都写在 unmounted,缓存切换时可能不会执行。

五、路由页面缓存要和 meta 配合设计

实际项目很少无脑缓存所有路由。 常见做法是在路由 meta 中声明是否缓存,再在布局组件里判断。 这样缓存策略集中在路由配置里,更容易维护。

{
  path: '/users',
  component: UserList,
  meta: { keepAlive: true },
}

流程示意:

进入路由
  -> 读取 route.meta.keepAlive
  -> true 包进 KeepAlive
  -> false 正常渲染

编辑页通常不缓存,因为缓存旧表单可能造成误提交。 列表页常缓存,因为用户从详情返回时希望保留筛选和页码。

六、缓存会带来内存和数据新鲜度成本

keep-alive 不是性能银弹。 缓存越多,内存占用越高;组件状态保留越久,数据越可能过期。 所以要配合 max、刷新策略和清理逻辑。

适合缓存:
  列表页、Tab 内容、搜索结果页
谨慎缓存:
  编辑页、支付页、权限敏感页、实时数据页

记忆钩子:keep-alive 让组件“下场休息”,不是“彻底退场”;回来走 activated,不是重新 mounted。

面试时补上这句,基本就能区分普通挂载生命周期和缓存生命周期。 真正工程里,缓存策略要和业务状态一起设计。

七、常见误区与追问

  • 误区:keep-alive 会让组件永远不销毁。 当不匹配缓存条件、超过 max 或父级销毁时,缓存实例仍可能被移除。
  • 误区:keep-alive 只缓存 DOM。 它缓存的是组件实例,状态、计算缓存和部分 DOM 状态都会被保留。
  • 误区:所有路由都应该缓存以提升性能。 缓存会占内存,也可能保留过期或敏感状态,必须按页面类型选择。
  • 追问:为什么 activated 不等于 mounted? mounted 是首次挂载,activated 是缓存组件重新激活,触发时机不同。
  • 追问:include 为什么有时不生效? 常见原因是组件 name 不匹配、异步组件命名不稳定或路由组件包裹方式不对。
  • 追问:列表页返回详情后如何保留筛选条件? 可以缓存列表页实例,也可以把筛选条件放路由 query 或 store,按业务选择。

八、加强记忆

这题抓住“缓存组件实例”这个核心。先讲默认切路由会销毁重建,keep-alive 让组件失活而不是卸载;再讲 include/exclude/max 控制范围;最后讲 activated/deactivated 和缓存成本,说明它适合列表页、Tab,不适合所有页面。