keepalive缓存机制

365 阅读4分钟

一、前言

keepalive的出现,让前端的生命周期得到了进一步的提升。

在组件化的今天,很多时候我们会从A页面跳转到B页面,还需要支持A页面数据的保存。

但是一般而言,在切换页面的时候,比如这里,从A页面切到B页面的时候,A页面就会默认被销毁了,这也是有利于性能的释放吧。

组件切换会导致组件被频繁销毁和重新创建, 性能不高。

但恰恰就是这个默认销毁,让我们不太好做到从B页面返回A页面时,A页面还保留着原先的信息,如果都是加载的就还好,请求多一遍数据就可以,但如果是用户输入的数据呢,总不能让用户再输入一遍吧,这很破坏用户体验感的。

所以keepalive的存在就很有必要了。

[keep-alive]是vue内置的一个组件,而这个组件的作用就是能够缓存不活动的组件,让我们返回该页面的时候,能看到之前的数据。

它自身不会渲染一个DOM元素,也不会出现在父组件链中;

使用[keep-alive]包裹动态组件时,会缓存不活动的组件实例,而不是销毁它们,这样就成为一种动态组件了。

所以才有这种说法,keep-alive可以提高组件的性能, 内部包裹的标签不会被销毁和重新创建, 触发激活和非激活的生命周期方法。

下面我们一起来看看这个重要的标签吧。

二、keepalive

1、相关周期函数

  • activated - 激活状态

    activated钩子:在组件第一次渲染时会被调用,
    之后在每次缓存组件被激活时调用。
    
    Activated钩子调用时机:第一次进入缓存路由/组件,在mounted后面,
    beforeRouteEnter守卫传给 next 的回调函数之前调用,并且给因为组件
    被缓存了,再次进入缓存路由、组件时,不会触发下面这些钩子函数,
    如beforeCreate created beforeMount mounted 都不会触发。
    
  • deactivated - 失去激活状态

    deactivated钩子调用时机:使用keep-alive就不会调用beforeDestroy
    (组件销毁前钩子)和destroyed(组件销毁),因为组件没被销毁,被缓存起来
    了,这个钩子可以看作beforeDestroy的替代,如果你缓存了组件,要在组件销
    毁的的时候做一些事情,可以放在这个钩子里。
    
    

组件内的离开当前路由,周期函数触发的顺序如下:

 钩子beforeRouteLeave => 
 路由前置守卫 beforeEach =>
 全局后置钩子afterEach => 
 deactivated 离开缓存组件 => 
 activated 进入缓存组件(如果你进入的也是缓存路由)
 
 

2、两个常用参数

include定义缓存白名单,keep-alive会缓存匹配上的组件;

exclude定义缓存黑名单,被匹配到的组件将不会被缓存;

为什么要有这两个参数呢?

因为项目里,我们基本上是会在router层级就使用keepalive包含我们的基本页面。

这样省事是省事了,不需要每新开一个页面就包一层keepalive标签,但也有个坏处是组件全部都缓存了,性能上大大的浪费,因为根据实际情况,可能就部分页面需要被缓存。

早期没有这两个参数,人们就是用v-if和router里的meta来界定

<keep-alive>
   <router-view v-if="$route.meta.keepAlive"/>
</keep-alive>
<router-view v-if="!$route.meta.keepAlive"/>

这种就是不够灵活,还容易引发bug,目前基本不这样写了。

所以就有include和exclude的出现。

它们的值可以是:数组或字符串或正则表达式

以上两个属性基本上需要和组件的name相互配合才是生效使用。

组件的name命名按规范是要驼峰式的,如 MyCode这样,然后根据include或者exclude去匹配组件的name,分别判定是否要进行缓存。

三、个人小疑惑

keepalive的缓存,在面对动态三级路由结构的时候,会引发整体网页layout布局的重新挂载,导致页面整体刷新了,包括路由菜单栏也一起刷新,这个问题我还是没能找到原因。静态三级路由就没有这个问题。

ps: 我是地霊殿__三無,希望能帮到你。

image.png