一、keep-alive和include到底是做什么的?
在Vue3项目里做性能优化时,keep-alive的include经常被用来精准控制组件缓存,但不少同学刚开始用总会碰到匹配不上、缓存没生效这些问题,今天就把keep-alive include的用法、场景、避坑点一次性讲清楚~
先搞明白基础概念:keep-alive是Vue3内置的一个组件,它的作用是缓存组件实例——简单说,组件切换时(比如路由跳转、组件切换),被keep-alive包裹的组件不会被销毁,下次再渲染时直接用缓存的实例,不用重新创建、请求数据、渲染DOM,能大幅提升性能。那include是keep-alive的一个属性,用来筛选哪些组件要被缓存,打个比方:keep-alive像个“仓库”,include就是“准入名单”,只有名字在名单里的组件,仓库才会给它留位置缓存;反之,exclude是“黑名单”,名单里的组件不准缓存(include优先级比exclude高)。
include的基础使用姿势有哪些?
知道是干啥的后,得学会怎么用,include的配置方式主要有三种,而且得和组件的name选项配合好:字符串形式(单组件缓存)
如果只有一个组件要缓存,直接写组件的name:
<keep-alive include="UserInfo"> <router-view></router-view> </keep-alive>
这时候,只有name为UserInfo
的组件会被缓存,其他组件走正常销毁-重建流程。
数组形式(多组件缓存)
需要缓存多个组件时,用数组存多个组件name:
<keep-alive :include="['HomePage', 'ArticleList']"> <router-view></router-view> </keep-alive>
这里要注意加v-bind
(简写),因为数组是动态数据~
正则形式(批量匹配)
如果想按“规则”匹配组件(比如所有以Admin
开头的组件),可以用正则:
<keep-alive :include="/^Admin/"> <router-view></router-view> </keep-alive>
同样要加v-bind
,因为正则是JS表达式,不过实际项目里正则用得少,因为组件name一般是明确的,数组更直观。
关键提醒:不管用哪种形式,组件必须显式声明name!比如用setup语法糖时,得用defineOptions
指定name:
<template>...</template> <script setup> defineOptions({ name: 'HomePage' // 必须和include里的名字完全一致 }) </script>
Vue3里用setup语法糖时,默认没有组件name(不像Vue2单文件组件会默认取文件名),所以一定要手动写name,否则include匹配不到!
实际项目里怎么用include优化性能?
光看语法没用,得结合场景,举个最常见的例子:列表页 + 详情页的切换。比如做一个博客系统,列表页(ArticleList)展示所有文章,点进去是详情页(ArticleDetail),每次从详情页切回列表页时,要是列表页重新渲染,就得重新请求接口、重新渲染表格,很浪费性能,这时候用keep-alive + include缓存列表页就很必要。
步骤拆解:
-
给列表页组件加name:
<!-- ArticleList.vue --> <template> <div class="article-list"> <!-- 文章列表内容 --> </div> </template> <script setup> defineOptions({ name: 'ArticleList' }) // 这里可以用onActivated和onDeactivated处理缓存前后的逻辑 import { onActivated, onDeactivated } from 'vue' onActivated(() => { console.log('列表页被激活,可做局部刷新') }) onDeactivated(() => { console.log('列表页被缓存,可保存临时状态') }) </script>
-
在布局组件里配置keep-alive:
假设所有页面通过router-view
渲染,在App.vue(或布局组件)里包裹:<template> <div id="app"> <keep-alive include="ArticleList"> <router-view></router-view> </keep-alive> </div> </template>
这样,ArticleList组件切换到其他页面(比如ArticleDetail)时,实例会被缓存;切回来时直接用缓存,不用重新请求数据、渲染DOM,性能秒提升~
这些坑踩过才知道要避!
用include时,很多问题都是“细节没注意”导致的,分享几个高频踩坑点:组件name没配或配错
前面强调过,Vue3用setup语法糖时必须手动写name,但还有个隐蔽问题:name的大小写要完全一致!比如组件name是ArticleList
,include里写成articleList
(驼峰变小写),就匹配不上,缓存不生效。
动态修改include不生效
如果想根据用户操作动态改缓存名单(比如用户点按钮,新增一个要缓存的组件),直接改普通数组没用,得用响应式数据:
<script setup> import { ref } from 'vue' const includeList = ref(['ArticleList']) // 用ref包数组,保证响应式 // 点击按钮后新增缓存组件 const addCache = () => { includeList.value.push('UserInfo') // 这样修改才会触发keep-alive更新 } </script> <template> <keep-alive :include="includeList"> <router-view></router-view> </keep-alive> <button @click="addCache">新增缓存组件</button> </template>
如果直接用const includeList = ['ArticleList']
(非响应式),修改数组不会触发keep-alive重新计算,缓存逻辑就乱了。
和Vue Router结合时的“元信息”误区
很多同学喜欢在路由元信息(meta)里配keepAlive: true
,然后在App.vue里判断:
<keep-alive :include="includeList"> <router-view v-slot="{ Component, route }"> <component :is="Component" v-if="route.meta.keepAlive" /> <component :is="Component" v-else /> </router-view> </keep-alive>
这时候要注意:路由组件的name必须和include里的name一致,而且如果是嵌套路由,子组件的缓存逻辑也得单独处理(比如父组件缓存了,子组件是否要缓存得看自己的name和include)。
Vue3和Vue2在include使用上的区别?
升级Vue3后,很多同学发现之前Vue2的写法突然不生效了,核心区别在组件name的默认行为:- Vue2:单文件组件(.vue)如果没写name,默认name是文件名的大驼峰形式(比如
my-component.vue
默认name是MyComponent
),所以include很容易匹配。 - Vue3:用
<script setup>
语法糖时,默认没有name(组件实例的name是undefined
)!必须用defineOptions({ name: 'xxx' })
显式声明,否则include根本找不到要缓存的组件。
举个🌰:Vue2里ArticleList.vue
不用写name,include="ArticleList"能直接匹配;但Vue3用setup语法糖时,必须手动写defineOptions({ name: 'ArticleList' })
,否则include匹配失败。
进阶:结合组合式API更灵活控制缓存
如果项目里有复杂场景(比如不同用户角色缓存不同组件、根据权限动态调整缓存名单),可以用组合式API封装逻辑,让include更智能:示例:根据用户角色动态生成include列表
<script setup> import { ref, watch } from 'vue' import { useUserStore } from '@/stores/user' // 假设用Pinia存用户信息 // 封装组合式API const useDynamicInclude = () => { const userStore = useUserStore() const include = ref([]) // 监听用户角色变化,动态改include watch(() => userStore.role, (newRole) => { if (newRole === 'admin') { include.value = ['AdminDash', 'AdminTable', 'AdminChart'] } else if (newRole === 'editor') { include.value = ['EditorDash', 'ArticleEdit'] } else { include.value = ['UserDash'] } }, { immediate: true }) // 初始化时立即执行 return { include } } const { include } = useDynamicInclude() </script> <template> <keep-alive :include="include"> <router-view></router-view> </keep-alive> </template>
这样不管是管理员、编辑还是普通用户,切换角色时缓存名单自动更新,不用在模板里写一堆判断,代码更简洁易维护~
Vue3里用keep-alive include要记住这几点:明确组件name、用响应式数据控制动态名单、结合场景避坑(尤其是Vue3和Vue2的name差异),把这些搞懂后,不管是列表页缓存、多角色权限适配,还是复杂路由场景,都能精准控制组件缓存,让项目性能起飞~要是你还有其他关于keep-alive的疑问,评论区随时聊~
版权声明
本文仅代表作者观点,不代表Code前端网立场。
本文系作者Code前端网发表,如需转载,请注明页面地址。
发表评论:
◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。