Vue2中使用keep-alive缓存组件

在Vue项目中,有些组件需要缓存状态,不需要重复渲染,在这个时候keep-alive就派上用场了,在这家公司已经快五个月了,从来没用上过这个功能,本来就不是特别了解现在更模糊不清了,突然想起来这个功能就翻了翻官方文档,顺便做个笔记,水一期博客。

缓存动态组件

keep-alive最基础的功能就是用来缓存组件,这样在你切换组件之后重新打开缓存的组件并不会重新渲染,体验较好且能保留状态。

1
2
3
4
5
6
7
8
9
10
<keep-alive>
<component :is="curComponent"></component>
</keep-alive>
<script>
data(){
return {
curComponent: TestComponent // 这里是组件
}
}
</script>

当然仅仅只是这样用来缓存组件的用法其实并不多,大多时候都是拿来配置<router-view>使用的

配合router-view使用

我们在做项目的时候经常需要将一整个路由页面缓存下来,尤其是后台管理项目,标签页感觉都已经是标配了。我们通常会把路由组件是否需要缓存配置在路由的meta元信息中,比如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// router.js
const routes = [
{
name: 'A',
path: '/a',
component: A,
meta: {
keepAlive: true
}
},
{
name: 'B',
path: '/b',
component: B,
meta: {
keepAlive: false
}
}
]

然后我们可以根据元信息进行判断是否需要缓存

1
2
3
4
<keep-alive>
<router-view v-if="$router.meta.keepAlive"></router-view>
</keep-alive>
<router-view v-if="!$router.meta.keepAlive"></router-view>

这样子就可以根据元信息来缓存路由组件了,不过确实是不太优雅,所以vue在后续版本中也为keep-alive加入了新属性

keep-alive新属性

Keep-alive在几次更新中加入了三个新属性:

  • include: 要缓存的路由组件
  • exclude: 不需要缓存的路由组件
  • max: 缓存组件的最大数

max接收一个数字表示最多可以缓存多少个组件实例,如果这个数字达到了,在新实例创建之前,已缓存组件中最久没有被访问的实例会被销毁。

1
2
3
<keep-alive :max="10">
<component :is=""></component>
</keep-alive>

include和exclude的用法是一样的,都可以接收三种类型的数据:

  • 字符串,可以用逗号分隔
1
2
<keep-alive include="a, b">
</keep-alive>
  • 正则表达式
1
2
<keep-alive :include="/a|b/">
</keep-alive>
  • 数组
1
2
<keep-alive :include="['a','b']">
</keep-alive>

所以如果我们的路由配置在本地,那么就没必要在元信息中配置keepAlive了,只要将需要缓存的组件名放到include中就可以。如果路由存储在服务器,那么我们还是需要进行配置,然后筛选需要缓存的组件放入到include中。

1
2
3
<keep-alive :include="['a','b']">
<router-view></router-view>
</keep-alive>

生命周期钩子函数

在keep-alive包含的组件会多出两个新的钩子函数:

  • activated:在组件被激活时调用。在组件第一次渲染时会被调用,之后每次keep-alive激活都会被调用
  • deactivated:在组件被停用时调用

在vue2.2.0及更高版本中可以触发新的钩子函数

当组件在 <keep-alive> 内被切换,它的 activateddeactivated 这两个生命周期钩子函数将会被对应执行。如果组件使用exclude排除这两个钩子不会被调用。

服务端渲染时这两个钩子函数也是不能调用的。

注意

include和exclude都是先匹配被包含组件的name字段,注意是组件的name字段,而不是路由的name

如果name字段不可用,则匹配它的局部注册名称 (父组件 components 选项的键值)。匿名组件不能被匹配。

keep-alive和transition类似,是一个抽象组件,并不会创建一个dom元素

都一个组件在include和exclude中都存在时,会以exclude为主,即该组件不会被缓存。

动态判断是否缓存组件

一个简单的小示例,假设我们有两个组件A,B。我们动态判断是否缓存B组件。我们的需求是从B跳转到A的时候,不再缓存B组件,其他时候需要缓存B组件。

我们可以通过监听$route,判断路由来实现动态修改需要缓存的组件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<keep-alive :include="keepAlive">
<router-view></router-view>
</keep-alive>
<script>
export default {
data(){
return {
keepAlive: ['a', 'b']
}
},
watch: {
$route(to, from){
if(form.name === 'b' && to.name === 'a'){
this.keepAlive = ['a']
}else{
this.keepAlive = ['a', 'b']
}
}
}
}
</script>
作者

胡兆磊

发布于

2022-03-31

更新于

2022-10-23

许可协议