Keep-Alive 源码解读

121 阅读4分钟

一般使用的到的场景

  1. 从 详情页 --> 列表页 的时候页面的状态是缓存,不用重新请求数据,提升用户体验
  2. 有一个可以进行筛选的列表页List.vue,点击某一项时进入相应的详情页面,等到你从详情页返回List.vue时,发现列表页居然刷新了!刚刚的筛选条件都没了!!!
  3. 页面中有大量的canvas、svg等等比较耗费性能的渲染时 例如:”浙江碳普惠“中首页用到了konva、lottie,首页多次切换会产生大量内存占用,于是对首页进行了缓存,但是有个问题是有些数据还是要及时更新,所以用到了onActivated这个钩子,在里面进行相关逻辑的处理。

keep-alive是什么

  • keep-alive是一个Vue全局组件
  • keep-alive本身不会渲染出来,也不会出现在父组件链中
  • keep-alive包裹动态组件时,会缓存不活动的组件,而不是销毁它们

keep-alive怎么用

1、router配置缓存

1)第一步:配置App.vue

  • vue2.x与vue3.0的App.vue配置有差异,在App.vue配置信息如下:
  • vue2.x中,router-view可整个放入keepalive中,如下:
<template>
<!-- vue2.x配置 -->
  <keep-alive>
    <router-view v-if="$route.meta.keepAlive" />
  </keep-alive>
  <router-view v-if="!$route.meta.keepAlive"/>
</template>
复制代码
  • vue3.0的App.vue配置方法如下:
<template>
  <!-- vue3.0配置 -->
  <router-view v-slot="{ Component }">
    <keep-alive>
      <component :is="Component"  v-if="$route.meta.keepAlive"/>
    </keep-alive>
    <component :is="Component"  v-if="!$route.meta.keepAlive"/>
  </router-view> 
</template>
复制代码

2)第二步:添加meta属性

在对应的路由上添加meta属性来设置页面是否要使用缓存,如下:

{
  path: "/keepAliveTest",
   name: "keepAliveTest",
   meta: {
       keepAlive: true //设置页面是否需要使用缓存
   },
   component: () => import("@/views/keepAliveTest/index.vue")
 },
复制代码

到此即可实现页面的简单缓存,但是有些场景需要做复杂处理,比如说页面部分信息不需要读缓存,每次进入都需要进行处理,这个时候我们就可以使用activated生命周期来解决页面部分刷新问题。

3)实现页面部分刷新

先了解vue的生命周期,被keepAlive包裹的组件和页面,页面进入时执行的生命周期为:created->mounted->activated; 其中created->mounted是页面第一次进入才会执行,activated生命周期在页面每次进入都会执行,特属于keepAlive的一个生命周期,所以我们把页面每次进来要进行的操作放入该生命周期即可。 如下代码:

activated() {
	// 页面每次进入将手机动态验证码置为空
   this.$refs.mobPwdCode.inputValue = '';
},
复制代码

实现的功能是用户每次进入将动态验证码设为空,实现此功能也可以用其他方式,比如说将该组件放缓存外(参见2、component配置缓存)。

4)动态设置路由keepAlive属性

有些时候我们用完了keepalive缓存之后,想让页面不再保持缓存,或者设置下一个页面keepalive,也这个时候我们可以改变meta的keepAlive值来去除页面缓存,使用beforeRouteEnter、beforeRouteUpdate、beforeRouteLeave,使用方式如下:

// to为即将跳转的路由,from为上一个页面路由
beforeRouteLeave(to, from,+ next) {
    // 设置下一个路由的 meta
    to.meta.keepAlive = false;
    next();
}
复制代码

2、组件配置缓存

1)使用场景

通常我们会对vue的一个页面进行缓存,然而有些时候我们仅需要缓存页面的某一个组件,或是在使用动态组件compnent进行组件切换时需要对组件进行缓存。

2)缓存页面指定组件

当用于App.vue时,所有的路由对应的页面为项目所对应的组件,使用方法如下:
在keep-alive组件上使用include或exclude属性,如下:使用include
代表将缓存name为testKA的组件,

// APP.vue文件,将页面作为组件缓存
<router-view v-slot="{ Component }">
  <keep-alive include="testKA">
    <component :is="Component"/>
  </keep-alive>
</router-view>
复制代码

在router对应的页面中,需要设置name属性,如下:

export default {
    name:'testKA',// keep-alive中include属性匹配组件name
    data() {return {}},
    activated() {
        // keepalive缓存的页面每次进入都会进行的生命周期
    },
}

复制代码

此外,include用法还有如下:

<!-- 逗号分隔字符串 -->
<keep-alive include="a,b">
  <component :is="view"></component>
</keep-alive>

<!-- 正则表达式 (使用 `v-bind`) -->
<keep-alive :include="/a|b/">
  <component :is="view"></component>
</keep-alive>

<!-- 数组 (使用 `v-bind`) -->
<keep-alive :include="['a', 'b']">
  <component :is="view"></component>
</keep-alive>
复制代码

exclude用法与include用法相同,代表不被缓存的组件。此外,keep-alive还有一个max属性,代表缓存组件最大数量,一旦这个数字达到了,在新实例被创建之前,已缓存组件中最久没有被访问的实例会被销毁掉。

<keep-alive :max="10">
  <component :is="view"></component>
</keep-alive>
[复制代码]([url]([url](url)))

当用于某个页面进行组件切换时,用法与缓存路由相同,不过只是将页面降级为一个组件,父组件由App.vue降级为对应路由页面。