Vue.js - 路由 vue-router 的使用详解5(keep-alive使用1:缓存组件)
<keep-alive> 是 Vue 的内置组件,它能在组件切换过程中将状态保存在内存中,防止重复渲染 DOM。下面通过样例进行演示。
一、配合组件使用
1,使用样例
(1)效果图
- 这是一个简单的 Tab 标签切换效果。当标签切换时,下方的两个自定义组件会随之切换显示。
- 由于两个子组件是包裹在 <keep-alive> 中,可以看到它们来回切换后,原来页面的内容和数据仍然保留,说明组件消失时并没有被销毁,而是缓存起来。

(2)样例代码
- 子组件1(child1.vue)
<template>
<div>
<h3>子页面1</h3>
<input type="text" name="" value="">
</div>
</template>
<script>
export default {
name: 'child1',
data() {
return {
}
},
//keep-alive钩子函数:组件被激活时调用
activated() {
console.log('子页面1被激活');
},
//keep-alive钩子函数:组件消失,被缓存时调用
deactivated() {
console.log('子页面1被缓存');
}
}
</script>
- 子组件2(child2.vue)
<template>
<div>
<h3>子页面2</h3>
<input type="text" name="" value="">
</div>
</template>
<script>
export default {
name: 'child2',
data() {
return {
}
},
//keep-alive钩子函数:组件被激活时调用
activated() {
console.log('子页面2被激活');
},
//keep-alive钩子函数:组件消失,被缓存时调用
deactivated() {
console.log('子页面2被缓存');
}
}
</script>
- 主页面(index.vue)
<template>
<div>
<div class="navi">
<div :class="{'selected':index === 1}" @click="changeIndex(1)">Tab1</div>
<div :class="{'selected':index === 2}" @click="changeIndex(2)">Tab2</div>
</div>
<div class="container">
<keep-alive>
<Child1 v-if="index === 1">
</Child1>
<Child2 v-else>
</Child2>
</keep-alive>
</div>
</div>
</template>
<script>
import Child1 from './child1.vue';
import Child2 from './child2.vue';
export default {
data() {
return {
index: 1, //当前选中标签页索引
}
},
components: {
Child1,
Child2,
},
methods: {
changeIndex(index) {
this.index = index;
}
}
}
</script>
<style>
.navi {
height: 60px;
line-height: 60px;
display: flex;
border-bottom: 1px solid #e5e5e5;
}
.navi > div {
flex: 1;
text-align: center;
}
.selected {
color: red;
}
</style>
(3)上面主页面(index.vue)的代码可以换种写法,改成动态组件,效果也是一样的。
<template>
<div>
<div class="navi">
<div :class="{'selected':index === 1}" @click="changeIndex(1)">Tab1</div>
<div :class="{'selected':index === 2}" @click="changeIndex(2)">Tab2</div>
</div>
<div class="container">
<keep-alive>
<component :is="currentView"></component>
</keep-alive>
</div>
</div>
</template>
<script>
import Child1 from './child1.vue';
import Child2 from './child2.vue';
export default {
data() {
return {
index: 1, //当前选中标签页索引
currentView: "Child1"
}
},
components: {
Child1,
Child2,
},
methods: {
changeIndex(index) {
this.index = index;
this.currentView = "Child" + index;
}
}
}
</script>
<style>
.navi {
height: 60px;
line-height: 60px;
display: flex;
border-bottom: 1px solid #e5e5e5;
}
.navi > div {
flex: 1;
text-align: center;
}
.selected {
color: red;
}
</style>
2,钩子函数
(1)<keep-alive> 提供了如下两个生命周期钩子函数:
(2)这两个钩子函数要注意的是:

- activated():组件被激活时调用。即组件第一次渲染时会被调用,之后每次 keep-alive 激活时也会被调用。通常我们可以在这个方法中实现:每次进入页面的时候获取最新的数据。
- deactivated():组件被停用时调用。
(2)这两个钩子函数要注意的是:
- 只有组件被 keep-alive 包裹时,这两个生命周期函数才会被调用,如果作为正常组件使用,是不会被调用的。
- 即使组件被 keep-alive 包裹,如果使用 exclude 排除之后,,这两个钩子依然不会被调用。
(3)上面样例中我们在子组件内部的钩子函数中输出了一些信息,当我们打开页面,先切换到标签 2 再切回标签 1,控制台输出如下:

3,选择性地缓存部分组件
(1)有时我们并不需要将 <keep-alive> 内的所有组件都进行缓存,<keep-alive> 提供了如下两个属性来实现这个需求:
- include:只有匹配的组件会被缓存(支持字符串或正则表达)
- exclude:任何匹配的组件都不会被缓存(支持字符串或正则表达)
(2)使用样例
- 只缓存 name 为 child1 的组件:
<keep-alive include="child1"> <component :is="currentView"></component> </keep-alive>
- 不缓存 name 为 child1 的组件:
<keep-alive exclude="child1"> <component :is="currentView"></component> </keep-alive>
- 只缓存 name 为 child1 或 child2 的组件:
<keep-alive include ="child1,child2"> <component :is="currentView"></component> </keep-alive>
- 只缓存以 child 开头的组件(使用正则表达式,需使用 v-bind):
<keep-alive :include="/^child.*/"> <component :is="currentView"></component> </keep-alive>
- 也可以动态绑定需要缓存的组件:
<keep-alive :include="includedComponents"> <component :is="currentView"></component> </keep-alive>
