Vue中keep-alive的深入理解和使用
什么是 keep-alive
?
在平常开发中,有部分组件没有必要多次初始化,这时,我们需要将组件进行持久化,使组件的状态维持不变,在下一次展示时,也不会进行重新初始化组件。
也就是说,kee-alive
是 Vue
内置的一个组件,可以使被包含的组件保留状态,或避免重新渲染 。也就是所谓的组件缓存
基本用法
//被keep-alive包含的组件会被缓存
<keep-alive>
<component />
</keep-alive>
被 keep-alive 包含的组件不会被再次初始化,也就意味着不会重走生命周期函数。
但是有时候是希望我们缓存的组件可以能够再次进行渲染,这时 Vue 为我们解决了这个问题
被包含在 keep-alive
中创建的组件,会多出两个生命周期的钩子: activated
与 deactivated
:
activated
当keep-alive
包含的组件再次渲染的时候触发deactivated
当keep-alive
包含的组件销毁的时候触发
keep-alive
是一个抽象的组件,缓存的组件不会被mounted
,为此提供activated
和deactivated
钩子函数
在2.1.0 版本后keep-alive
新加入了两个属性: include
(包含的组件缓存生效) 与 exclude
(排除的组件不缓存,优先级大于include
) 。
参数理解
keep-alive
可以接收3个属性做为参数进行匹配对应的组件进行缓存:
-
include
包含的组件(可以为字符串,数组,以及正则表达式,只有匹配的组件会被缓存) -
exclude
排除的组件(以为字符串,数组,以及正则表达式,任何匹配的组件都不会被缓存) -
max
缓存组件的最大值(类型为字符或者数字,可以控制缓存组件的个数)
注:当使用正则表达式或者数组时,一定要使用v-bind
// 只缓存组件name为a或者b的组件
<keep-alive include="a,b">
<component />
</keep-alive>
// 组件name为c的组件不缓存(可以保留它的状态或避免重新渲染)
<keep-alive exclude="c">
<component />
</keep-alive>
// 如果同时使用include,exclude,那么exclude优先于include, 下面的例子只缓存a组件
<keep-alive include="a,b" exclude="b">
<component />
</keep-alive>
// 如果缓存的组件超过了max设定的值5,那么将删除第一个缓存的组件
<keep-alive exclude="c" max="5">
<component />
</keep-alive>
配合router
使用
router-view
也是一个组件,如果直接被包在keep-alive
里面,那么所有路径匹配到的视图组件都会被缓存,如下:
<keep-alive>
<router-view>
<!-- 所有路径匹配到的视图组件都会被缓存! -->
</router-view>
</keep-alive>
如果只想要router-view
里面的某个组件被缓存,怎么办?
- 使用
include/exclude
- 使用
meta
属性
1.使用 include
(exclude
例子类似)
//只有路径匹配到的 name 为 a 组件会被缓存
<keep-alive include="a">
<router-view></router-view>
</keep-alive>
2.使用 meta
属性
// routes 配置
export default [
{
path: '/',
name: 'home',
component: Home,
meta: {
keepAlive: true // 需要被缓存
}
}, {
path: '/profile',
name: 'profile',
component: Profile,
meta: {
keepAlive: false // 不需要被缓存
}
}
]
<keep-alive>
<router-view v-if="$route.meta.keepAlive">
<!-- 这里是会被缓存的视图组件,比如 Home! -->
</router-view>
</keep-alive>
<router-view v-if="!$route.meta.keepAlive">
<!-- 这里是不会被缓存的视图组件,比如 Profile! -->
</router-view>
防坑指南
keep-alive
先匹配被包含组件的name
字段,如果name
不可用,则匹配当前组件components
配置中的注册名称。keep-alive
不会在函数式组件中正常工作,因为它们没有缓存实例。- 当匹配条件同时在
include
与exclude
存在时,以exclude
优先级最高(当前vue 2.4.2 version)。比如:包含于排除同时匹配到了组件A,那组件A不会被缓存。 - 包含在
keep-alive
中,但符合exclude
,不会调用activated
和deactivated
。
keep-alive的生命周期
- 初次进入时:created > mounted > activated;退出后触发 deactivated
- 再次进入:会触发 activated;事件挂载的方法等,只执行一次的放在 mounted 中;组件每次进去执行的方法放在 activated 中
<template>
<div id="app">
<!-- <img src="./assets/logo.png"> -->
<ul>
<li><router-link to='/'>helloworld</router-link><li>
<li><router-link to='/echart'>echart</router-link><li>
<li><router-link to='/map'>map</router-link></li>
</ul>
<!-- <router-view></router-view> -->
<!-- 方法一:缓存所有的 -->
<keep-alive>
<router-view/>
</keep-alive>
<!-- 方法二 -->
<!-- 缓存模块名为List的模块,不会重复请求,其它模块重复请求 -->
<keep-alive include="List">
<router-view/>
</keep-alive>
<!-- 不缓存模块名为List的模块,会重复请求,其它模块缓存 -->
<keep-alive exclude="List">
<router-view/>
</keep-alive>
<!-- 方法三 -->
<keep-alive>
<router-view v-if="$route.meta.keepAlive"></router-view>
</keep-alive>
<router-view v-if="!$route.meta.keepAlive"></router-view>
</div>
</template>
<script>
export default {
name: 'App'
// activated,deactivated这两个生命周期函数一定是要在使用了keep-alive组件后才会有的,否则则不存在
activated(){
console.log('activated页面打开时触发');
},
deactivated(){
console.log('deactivated页面关闭时触发');
}
}
</script>
<style scoped>
</style>