作用说明
一个应用场景 :
当我们在进行路由跳转的时候,会用到<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