导读:本期聚焦于乙爱丽丝创作的《Vue 3 中 keep-alive 的 include、exclude 与 max 属性如何配合使用?》,敬请观看详情。keep-alive 为什么有时缓存不生效?问题往往出在组件 name 与 include 的匹配规则上。Vue 3 的 keep-alive 提供 include、exclude 和 max 三个属性来精确控制哪些组件进入缓存池、哪些被排除以及缓存上限。include 和 exclude 都支持字符串、正则表达式和数组,匹配目标是组件选项中的 name 字段,而不是路由名称或文件名。max 则限制缓存实例数量,当达到上限后,最久没有被访问的组件实例会被销毁,类似于 LRU 淘汰策略。理解这三者之间的关系,可以避免列表页状态丢失、表单数据被清空以及内存占用过高的问题。本文会从缓存机制讲起,逐步演示三个属性的不同写法,再分析动态包含与路由缓存中的常见坑,最后给出一个结合用户权限和页面层级的组合策略,帮助你更稳妥地管理 Vue 3 应用中的组件状态。

在 Vue 3 单页应用里,组件切换时默认会被销毁并重新创建,这会导致列表滚动位置、表单输入、分页状态等丢失。keep-alive 的作用就是在组件切换时把不活动的组件实例缓存起来,而不是直接销毁。它常用于动态组件和路由视图,但仅靠默认的全局缓存往往不够精细,缓存太多组件还会占用内存,include、exclude、max 三个属性正是为了精确控制缓存范围与上限而设计的。接下来会从匹配规则到实战组合逐一说明。

Vue 3 中 keep-alive 的 include、exclude 与 max 属性如何配合使用?

一、keep-alive 的缓存机制与匹配原理

要理解 include、exclude 和 max,先要明白 keep-alive 内部做了什么。默认情况下,Vue 在切换动态组件时会卸载旧组件实例,触发 unmounted 生命周期,组件内的所有响应式数据、DOM 状态都会被清理。而使用 <keep-alive> 包裹后,组件不会被真正卸载,而是被移入一个缓存对象中,页面上的 DOM 节点也被保留,只是切换时不再显示。此时组件会触发 deactivated 生命周期,而不是 unmounted;当切换回来时会触发 activated。这两个生命周期对于列表页恢复滚动位置、暂停轮询请求等场景非常有用。

include 和 exclude 控制的是哪些组件可以进入这个缓存对象。它们匹配的不是路由配置里的 name,也不是组件文件名,而是组件定义中的 name 选项。Vue 3 中如果使用普通选项式 API,可以直接在组件里写 name: 'HomePage';如果使用 <script setup>,由于默认无法直接声明 name,需要借助 defineOptions 来显式指定,例如 defineOptions({ name: 'HomePage' })。很多项目里缓存不生效,往往就是因为组件没有声明 name,导致 include 匹配不到目标。

缓存时 Vue 会以组件 name 作为 key 保存实例。同一个组件在不同路由下如果复用同一个 name,也会共享缓存实例,这通常不是期望的行为,因此每个需要独立缓存的页面都应该有唯一的 name。下面是一个基础示例:

<template>
  <keep-alive include="HomePage,ListPage">
    <component :is="currentTab" />
  </keep-alive>
</template>

<script setup>
import { ref } from 'vue';
import HomePage from './HomePage.vue';
import ListPage from './ListPage.vue';

const currentTab = ref('HomePage');
</script>

二、include 和 exclude 的写法与优先级

include 和 exclude 都支持三种数据类型:字符串、正则表达式和数组。字符串形式使用逗号分隔多个组件名,例如 include="HomePage,ListPage";正则形式直接传入一个正则对象,例如 :include="/^Page/",表示匹配所有以 Page 开头的组件 name;数组形式则列出明确的 name 字符串,例如 :include="['HomePage', 'ListPage']"。在实际项目中,数组形式最常用,因为它便于从路由配置中动态生成。

当 include 和 exclude 同时出现并产生冲突时,exclude 的优先级更高。也就是说,如果一个组件既被 include 包含又被 exclude 排除,最终该组件不会被缓存。这个规则适合做全局排除,比如所有页面都缓存,但登录页、注册页、404 页等不想保留状态,就可以使用 exclude 来剔除。另外 exclude 也可以单独使用,不设置 include 时表示除 exclude 匹配项之外的组件都缓存。

include 和 exclude 是响应式的,动态修改它们会立即影响缓存。当某个组件不再满足 include 条件或开始满足 exclude 条件时,它对应的缓存实例会被立即销毁,触发 unmounted。这在使用权限控制或动态标签页时非常有用,可以避免敏感数据长时间留在内存中。下面是一个动态 include 的示例:

<template>
  <keep-alive :include="cachedPages">
    <router-view />
  </keep-alive>
</template>

<script setup>
import { computed } from 'vue';
import { useRoute } from 'vue-router';

const route = useRoute();

const cachedPages = computed(() => {
  // 根据路由 meta.keepAlive 动态生成需要缓存的组件名
  return route.matched
    .filter(r => r.meta?.keepAlive)
    .map(r => r.components?.default?.name)
    .filter(Boolean);
});
</script>

三、max 属性如何限制缓存数量与淘汰策略

max 属性接收一个数字,用于限制 keep-alive 最多缓存多少个组件实例。如果不设置 max,缓存数量不受限制,在一个包含大量页面的应用里,内存占用会持续增长。设置一个合理的 max 值可以在保留常用页面状态的同时,防止内存过度膨胀。比如后台管理系统中经常切换的页面可能只有十几个,设置 :max="10" 就能覆盖大多数使用场景。

当缓存实例数量达到 max 上限后,再有新的组件需要缓存时,keep-alive 会淘汰最久没有被访问的组件实例。这种策略类似于 LRU(Least Recently Used,最近最少使用)。具体表现为:每次组件被激活时,它在缓存队列中的位置会被移到最新;而一直闲置的组件会逐渐被挤到队尾。超过 max 后,队尾的组件实例会被销毁。这个销毁过程是完整的,会触发该组件的 unmounted 生命周期,相关状态也随之释放。

需要注意一点:max 与 include、exclude 叠加时,max 的淘汰范围是当前已经缓存的组件。即使某个组件在 include 列表中,如果它长期没有被访问,而缓存数量又达到了 max,它依然会被淘汰。反过来,被 exclude 排除的组件根本不会进入缓存,不会占用 max 名额。因此,在设置 include 时不要以为只要写进去就会一直缓存,还要结合 max 和实际访问频率来考虑。下面展示 max 的使用:

<template>
  <keep-alive :include="['HomePage', 'ListPage', 'DetailPage']" :max="2">
    <component :is="currentView" />
  </keep-alive>
</template>

在上面的例子中,虽然 include 允许缓存三个组件,但 max 限制为 2,所以最多只能同时保留两个实例。如果用户依次打开 HomePage、ListPage、DetailPage,HomePage 会被淘汰,因为它是前两个中最久未访问的。

四、组合使用与常见问题

把 include、exclude、max 结合起来,可以设计一套分层缓存方案。比如全站页面默认通过 <keep-alive> 包裹,然后使用 exclude 排除登录、注册、404 等不需要缓存的页面;通过路由 meta 动态生成 include 列表,只缓存核心业务页面;最后设置一个 max 值,比如 15 或 20,来兜底控制内存。这种方式既能保证用户返回列表页时状态还在,又不会因为缓存过多页面导致性能问题。

实际操作中有几个常见的坑需要注意。第一是组件 name 与路由 name 的混淆。路由配置里的 name 是路由名称,include/exclude 匹配的是组件内的 name 选项,两者可能相同也可能不同,不要混用。第二是动态组件切换时,如果组件没有声明 name,include 会直接忽略它,导致缓存不生效,排查时可以先打印组件实例的 $.type.name 确认。第三是 include 数组动态变化后,被移除的组件缓存会被销毁,之前保留的表单数据会丢失,因此不要频繁修改 include,最好基于稳定的业务模块来划分。

还有一个容易忽略的点:keep-alive 包裹的是 <router-view> 或 <component>,如果组件内部还有嵌套的 keep-alive,外层的 max 和内层缓存会相互影响。一般情况下不建议多层嵌套 keep-alive,除非有明确的父子页面需要独立缓存。合理规划 include、exclude 和 max,可以让 Vue 3 应用的页面状态管理既灵活又可控。

Vue 3 keep-alive组件缓存include exclude max修改时间:2026-09-29 09:45:49

免责声明:已尽一切努力确保本网站所含信息的准确性。网站作品多为原创整理与精心创作,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们进行处理Email:chomcom@qq.com。
引用或转载本作品时,请注明当前出处:https://www.ipipp.com/html/0929/63352.html,基于非商业用途的前提下,欢迎转载或二创本作品。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。