keep-alive 简介
keep-alive 是 Vue 内置的一个组件,可以使被包含的组件保留状态,或避免重新渲染。
用法
<keep-alive>
<component>
<!-- 该组件将被缓存! -->
</component>
</keep-alive>
props
- include - 字符串或正则表达,只有匹配的组件会被缓存
- exclude - 字符串或正则表达式,任何匹配的组件都不会被缓存
2.1.0 新增
include 和 exclude 属性允许组件有条件地缓存。二者都可以用逗号分隔字符串、正则表达式或一个数组来表示:
<!-- 逗号分隔字符串 --> <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>
max
2.5.0 新增
最多可以缓存多少组件实例。一旦这个数字达到了,在新实例被创建之前,已缓存组件中最久没有被访问的实例会被销毁掉。
<keep-alive :max="10"> <component :is="view"></component> </keep-alive> <keep-alive> 不会在函数式组件中正常工作,因为它们没有缓存实例。
// 组件 a export default { name: 'a', data () { return {} } }
<keep-alive include="a">
<component>
<!-- name 为 a 的组件将被缓存! -->
</component>
</keep-alive>可以保留它的状态或避免重新渲染
<keep-alive exclude="a">
<component>
<!-- 除了 name 为 a 的组件都将被缓存! -->
</component>
</keep-alive>可以保留它的状态或避免重新渲染
但实际项目中,需要配合vue-router共同使用.
router-view 也是一个组件,如果直接被包在 keep-alive 里面,所有路径匹配到的视图组件都会被缓存:
<keep-alive>
<router-view>
<!-- 所有路径匹配到的视图组件都会被缓存! -->
</router-view>
</keep-alive>
如果只想 router-view 里面某个组件被缓存,怎么办?
// routes 配置 export default [ { path: '/', name: 'home', component: Home, meta: { keepAlive: true // 需要被缓存 } }, { path: '/:id', name: 'edit', component: Edit, meta: { keepAlive: false // 不需要被缓存 } } ]
<keep-alive>
<router-view v-if="$route.meta.keepAlive">
<!-- 这里是会被缓存的视图组件,比如 Home! -->
</router-view>
</keep-alive>
<router-view v-if="!$route.meta.keepAlive">
<!-- 这里是不被缓存的视图组件,比如 Edit! -->
</router-view>
这两个钩子需要配合配合<keep-alive><keep-alive/>来使用
keep-alive的作用会缓存不活动的组件实例,而不是销毁它们。当组件在<keep-alive>内被切换,activated和deactivated这两个生命周期钩子函数将会被对应执行。
注意:activated,deactivated这两个生命周期函数一定是要在使用了keep-alive组件后才会有的,否则则不存在 当引入keep-alive的时候,页面第一次进入,钩子的触发顺序created-> mounted-> activated,退出时触发deactivated。当再次进入(前进或者后退)时,只触发activated。
用一个实例说明:
搭建了一个脚手架,新建2个子组件,1个父组件
子组件A内容
<template>
<div>
<div>componentA</div>
<button @click="show=!show" >componentA事件</button>
<div v-if='show'>componentA-2</div>
<div v-else>componentA-1</div>
</div>
</template>
<script>
export default {
name: 'componentA',
comments: {},
data() {
return {
show: true,
circle:'生命周期'
}
},
activated() {
console.group("activated 组件激活时执行 ");
},
deactivated() {
console.group("deactivated 组件停用时执行");
}
}
</script>
<style>
</style>
<template>
<div>
<div>componentB</div>
</div>
</template>
<script>
export default {
name: 'componentB',
compnents: {},
data() {
return {}
}
}
</script>
<style>
</style>
父组件内容
<template>
<div id="box">
<button @click="active='componentA'">componentA</button>
<button @click="active='componentB'">componentB</button>
<keep-alive>
<component :is='active' ></component>
</keep-alive>
</div>
</template>
<script>
import Vue from 'vue'
import componentA from '@/components/componentA'
import componentB from '@/components/componentB'
export default{
components:{
componentA,
componentB
},
data(){
return{
active:'componentB'
}
}
}
</script>
<style>
</style>
如果如下

这里看到当A组件被点击激活时就触发activated钩子,点击B组件开启A组件关闭时deactivated钩子就触发执行。
这里也能看出在keep-alive 里A组件的数据也被缓存起来,第二次触发的时候组件状态没有被重新改变