欢迎您访问 最编程 本站为您分享编程语言代码,编程技术文章!
您现在的位置是: 首页

Vue中的keep-alive缓存机制解析

最编程 2024-08-02 20:08:27
...

介绍

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缓存状态的组件会多出onActivatedonDeactivated两个生命周期钩子函数。

  • 首次调用组件会依次执行 setup -> onMounted -> onActivated,退出组件触发onDeactivated
  • 再次进入该组件页面时,onMounted以及之前的钩子函数都不会再执行,仅会触发onActivated函数,退出时执行onDeactivated。 因此,仅首次执行的操作可以放到setuponMounted中,而每次调用组件都要处理的逻辑可以放到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
}

接下来就可以根据具体业务需求结合生命周期钩子onActivatedonBeforeRouteLeave等路由钩子进行开发。

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();
});