作用说明
一个应用场景
当我们在进行路由跳转的时候,会用到 <router-view> 来作为 组件渲染的出口, 此时,组件的状态是不会被保持的。
比如 : 当前在【组件a】中有一个响应式状态 num 的值通过 自加的方式 从初始值0 变成了 100;
然后跳转到 【组件b】,
再次跳转 回到 【组件a】 的时候,num 的值会 恢复为初始值 0。
如何实现 回到 【组件a】的时候,仍然保持 num 的数据状态为 100 呢?
这就是本文要介绍的 keepalive 组件的作用。
它就是用来做组件状态保持的,或者叫做 缓存组件实例。
keepalive的简单介绍
1、 直接使用 <keep-alive> 标签,将目标组件包起来,就实现了组件的缓存;
2、配合路由的时候,需要使用到下面的格式 : 这个格式是固定的:
<router-view v-slot="{ component }">
<keep-alive>
<component :is="component" />
</keep-alive>
</router-view>
3、组件在缓存的时候,有两个声明周期钩子可以配合使用:
onactivated: 组件在被激活时触发ondeactivated: 组件在跳转走被缓存时触发
4、keepalive 有两个属性 :
include: 指定要缓存的组件exculde: 指定不要缓存的组件
以上两个属性 的值是 组件的名称, 可以是 数组的形式指定多个组件。
例如 : 有 两个组件,name 分别是 a 和 b
- 例1 :
<keep-alive include="a"> - 例2 :
<keep-alive :include="['a','b']">
注意,当是数组的时候,需要使用 :的形式。
代码案例
本案例 有两个普通的组件,分别包含了响应式状态,
app.vue 中通过 按钮 进行两个组件的切换;
- 观察 1:两个组件的响应式状态是否保存了 ;
- 观察2 :两个组件的声明周期钩子。
本案例的项目结构如下:
projectname
| -- src
| -- app.vue # 根组件
| -- componenta.vue # 组件a
| -- componentb.vue # 组件b
| -- main.ts # 程序入口文件
| -- router.ts # 路由配置文件
| -- index.html # 项目的入口文件案例代码
组件a componenta.vue
<template>
<div class="diva">
这是组件a
<br>
countnum : {{ countnum }}
<br>
<button @click="countnum++">+</button>
<button @click="countnum--">-</button>
</div>
</template>
<script setup lang="ts">
// 指定组件名称
defineoptions({
name:'ca'
})
import { ref,onmounted,onunmounted,onactivated,ondeactivated} from 'vue'
const countnum = ref(0)
// 组件挂载成功后
onmounted(()=>{
console.log('组件a onmounted')
})
// 组件卸载成功后
onunmounted(() => {
console.log('组件a onunmounted')
}),
// 组件激活
onactivated(()=>{
console.log('组件a onactivated')
})
// 组件失活
ondeactivated(()=>{
console.log('组件a ondeactivated')
})
</script>
<style scoped>
.diva{
width: 300px;
height: 200px;
background: red;
}
</style>
组件b componentb.vue
<template>
<div class="divb">
这是组件b
<br>
message : {{ message }}
<br>
输入框 :<input type="text" v-model="message" />
</div>
</template>
<script setup lang="ts">
// 指定组件名称
defineoptions({
name:'cb'
})
import { ref,onmounted,onunmounted,onactivated,ondeactivated} from 'vue'
const message = ref('')
// 组件挂载成功后
onmounted(()=>{
console.log('组件b onmounted')
})
// 组件卸载成功后
onunmounted(() => {
console.log('组件b onunmounted')
}),
// 组件激活
onactivated(()=>{
console.log('组件b onactivated')
})
// 组件失活
ondeactivated(()=>{
console.log('组件b ondeactivated')
})
</script>
<style scoped>
.divb{
width: 250px;
height: 150px;
background: green;
}
</style>
路由配置 router.ts
// 导入 定义路由的两个方法
import {createrouter,createwebhistory} from 'vue-router'
// 懒加载写法 : 先声明,下面直接使用
const componenta = () => import('./componenta.vue')
const componentb = () => import('./componentb.vue')
// 声明路由跳转的路径与组件的对应关系
const routslist = [
// 直接使用上面声明的组件
{path:'/a',name:'aroute',component:componenta},
{path:'/b',name:'broute',component:componentb}
]
// 创建路由的实例对象
const routerconfigobj = createrouter({
history:createwebhistory('abc'), // 带一个参数,表示是路由的一个前缀
routes:routslist // 指定路由的配置列表
})
// 导出路由的对象
export default routerconfigobj;
根组件 app.vue
<template>
<div class="basediv">
app.vue 中的 msg : {{ msg }}
<br>
<button @click="$router.push('/a')">跳转到a</button>
<button @click="$router.push('/b')">跳转到b</button>
<br>
<!-- 核心 : keep-alive 的使用 -->
<router-view v-slot="{ component }">
<!-- :exclude="['ca','cb']" -->
<keep-alive :include="['ca','cb']">
<component :is="component" />
</keep-alive>
</router-view>
</div>
</template>
<script setup lang="ts">
// 引入 provide 方法
import { ref } from 'vue'
// 声明父组件的一个变量
const msg = ref('这是app根组件的msg变量')
</script>
<style scoped>
.basediv{
width: 600px;
height: 400px;
border: 1px solid red;
}
</style>
运行结果
》1、初始状态 : 组件a中的数字执行几次自增

》2、点击 跳转到 组件b
| 点击前 | 跳转后 |
|---|---|
![]() | ![]() |
》3、组件b中的输入框输入内容

》4、点击跳转回 组件a

》5、再次跳转回 组件b

总结
以上为个人经验,希望能给大家一个参考,也希望大家多多支持代码网。


发表评论