一、前言
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: 我是地霊殿__三無,希望能帮到你。