Vue中的keep-alive缓存机制解析
介绍
1. 什么是keep-alive?
keep-alive是vue一个内置组件,用于保存组件状态,实现缓存,避免组件页面重复渲染及刷新。keep-alive包裹的组件会被放进内存中,使用时直接从缓存中调用,相当于用内存去换取速度。
2. 属性
keep-alive组件有以下3个属性:
-
include
:缓存白名单,接收字符串、正则表达式、数组类型的值,只有与之匹配的组件会被缓存。 -
exclude
:缓存黑名单,接收字符串、正则表达式、数组类型的值,相当于任何与之匹配的组件将不会被缓存。 -
max
:接收数字和字符串类型的参数,表示缓存组件上限,达到该值时,所有缓存组件中最久没有被访问的组件将被销毁。
使用示例:
<!--在实际应用中,include和exclude属性常使用数组类型的值-->
<keep-alive :include="['a', 'b']">
<component :is="view"></component>
</keep-alive>
<!--max表示最多能缓存的组件数-->
<keep-alive :max="10">
<component :is="view"></component>
</keep-alive>
include和exclude属性会优先匹配组件自身的name属性,如果name不可用,则会匹配它的局部注册名称 ,也就是父组件 中components
属性的键值。匿名组件不能被匹配。
3. 生命周期
以vue3组合API为例,使用keep-alive缓存状态的组件会多出onActivated
和onDeactivated
两个生命周期钩子函数。
- 首次调用组件会依次执行
setup -> onMounted -> onActivated
,退出组件触发onDeactivated
。 - 再次进入该组件页面时,
onMounted
以及之前的钩子函数都不会再执行,仅会触发onActivated
函数,退出时执行onDeactivated
。 因此,仅首次执行的操作可以放到setup
和onMounted
中,而每次调用组件都要处理的逻辑可以放到onActivated
中。
实践应用
1. 基本写法
组件缓存
组件缓存基本写法如下,其中is属性表示需要缓存的组件名称。某些时候我们只想将某个特定的组件进行缓存,或是在Tab页切换时,想要保存切换前页面的数据和状态,都可以利用keep-alive实现。
<!-- 基本写法 -->
<keep-alive>
<component :is="view"></component>
</keep-alive>
路由缓存
步骤一:配置App.vue
vue2写法:
<!--App.vue-->
<keep-alive>
<!-- 需要缓存的视图组件 -->
<router-view v-if="$route.meta.keepAlive"> </router-view>
</keep-alive>
<!-- 不需要缓存的视图组件 -->
<router-view v-if="!$route.meta.keepAlive"> </router-view>
vue3中写法有所调整,需要结合<component>
实现动态渲染
<!--App.vue-->
<router-view v-slot="{ Component }">
<!-- 需要缓存的视图组件 -->
<keep-alive>
<component :is="Component" :key="$route.name" v-if="$route.meta.keepAlive" />
</keep-alive>
<!-- 不需要缓存的视图组件 -->
<component :is="Component" :key="$route.name" v-if="!$route.meta.keepAlive" />
</router-view>
步骤二:配置路由文件,添加keepAlive属性
{
path: '/',
name: 'Home',
meta: {
keepAlive: true
},
component: Home
}
接下来就可以根据具体业务需求结合生命周期钩子onActivated
和onBeforeRouteLeave
等路由钩子进行开发。
2. 动态缓存实践
场景:在列表页A选定筛选条件后查询到某一数据条目,跳转至详情页B后返回,列表页需要保存之前的筛选条件及查询结果,从其他页面跳转或者从菜单进入列表页A则不保存。简而言之,需要根据是不是从详情页B返回到列表页A来控制A页面是否缓存,因此考虑结合onBeforeRouteLeave
钩子函数去实现:
// 配置路由文件
{
path: '/a',
name: 'A',
meta: {
keepAlive: true
},
component: A
}
// A页面
onBeforeRouteLeave((to, from, next) => {
if (to.name === 'B') {
from.meta.keepAlive = true;
} else {
from.meta.keepAlive = false;
}
next();
});
但是实践的时候出现了修改meta.keepAlive
属性不生效的情况,因此改用include属性结合vuex的解决方案,定义keepAlives存储需要缓存的组件名称,onBeforeRouteLeave
监听路由前进至详情页时设置A页面缓存,具体代码如下:
<!--App.vue-->
<router-view v-slot="{ Component }">
<keep-alive :include="keepAlives">
<component :is="Component"/>
</keep-alive>
</router-view>
// store.js
const state = {
keepAlives: []
};
const getters = {
keepAlives: (state) => state.keepAlives
};
const mutations = {
SET_KEEP_ALIVES(state, keepAlives) {
state.keepAlives = keepAlives;
}
}
// A页面
onBeforeRouteLeave((to, from, next) => {
if (to.name === 'B') {
store.commit(keepAlives, ['A']); //此处A为组件A注册的name名称
} else {
store.commit(keepAlives, []);
}
next();
});
推荐阅读
-
VUE] Vue 中的 keep-alive 组件Vue 中的 keep-alive 组件
-
Java_EE]Day04 MyBatis 中的关联映射和缓存机制
-
前端vue项目部署中,用户还在访问系统,存在缓存问题,部署后需要ctrlF5强制刷新,解决热更新的几种方案
-
Vue的钩子函数深度解析:路由导航守卫、keep-alive和生命周期钩子
-
实战经验分享:Vue中的$set使用及其常见问题解析
-
Vue中遇到新旧值相同的watch问题,该如何解决?——深度探究源码解析
-
全面解析:MySQL中的锁机制
-
Vue中的那些酷炫操作全解析!一文读懂
-
简化版!理解Vue中的动态组件与Keep-Alive缓存、Webpack的代码分割及异步组件、$ref引用元素/组件、组件生命周期和v-model详解
-
明白HTTP和TCP的Keep-Alive机制有何不同?解析详细说明