在 Vue 中,默认情况下,当一个组件实例被替换后会被销毁,导致丢失所有已变化的状态。这意味着当组件再次显示时,会创建一个只带有初始状态的新实例。然而,有时候我们希望在页面切换到其他页面再返回时能够保持之前的状态而不是重新初始化。为了实现这一点,Vue 提供了 keep-alive 组件,它可以包装动态组件,从而在组件切换时保留其状态。本篇文章就来实现如何控制部分组件的缓存
分别来到views/menu/index.vue和views/role/index.vue中,我们将其改为如下:
<template>
<div>
<div>菜单管理</div>
<div>
<el-button @click="count++">{{ count }}</el-button>
</div>
</div>
</template>
<script lang="ts" setup>
import { ref } from "vue";
const count = ref(0);
</script>
<style lang="scss"></style>
<template>
<div>
<div>角色管理</div>
<div>
<el-button @click="count++">{{ count }}</el-button>
</div>
</div>
</template>
<script lang="ts" setup>
import { ref } from "vue";
const count = ref(0);
</script>
点击按钮可以改变 count 的值,我们可以看到当我们切换到其他页面再返回时,count 的值会重新变为 0,这是因为我们没有使用 keep-alive 组件,所以当组件被销毁时,所有的状态都会被重置。
接下来我们来实现指定页面缓存的功能。首先看一下和后端约定的缓存字段
这里是当 meta 中的 catch 为 1 时,才会缓存该页面。并且需要将meta.name添加到需要缓存的组件数组中(这里的 name 取得是路由最后一级然后将其首字母大写)
在store/index.ts定义一个需要缓存的组件数组,以及一个添加缓存组件的方法
然后在layout/components/AppMain/index.vue引入keep-alive组件,并设置include属性为缓存的组件数组
<template>
<div class="app_main">
<router-view v-slot="{ Component, route }">
<transition name="fade" mode="out-in">
<keep-alive :include="appStore.catchList">
<component :is="Component" :key="route.path" />
</keep-alive>
</transition>
</router-view>
</div>
</template>
<script lang="ts" setup>
import "./index.scss";
import useApp from "@/store";
const appStore = useApp();
</script>
最后在路由守卫中添加需要缓存的组件,当路由发生变化时,判断当前路由是否需要缓存,如果需要缓存,则将其添加到缓存数组中(utils/routeUtils.ts)
到这里其实还没有实现全部的功能,我们还需要在需要缓存的组件中将组件名定义成后端返回的meta.name一致才能实现当前组件的缓存,这里可以使用 vue3 提供的宏函数defineOptions为组件命名
<template>
<div>
<div>菜单管理</div>
<div>
<el-button @click="count++">{{ count }}</el-button>
</div>
</div>
</template>
<script lang="ts" setup>
import { ref } from "vue";
defineOptions({
name: "Menu",
});
const count = ref(0);
</script>
<style lang="scss"></style>
最后我们将数据库中将菜单管理的 catch 改为 1,然后刷新页面,点击按钮看一下菜单管理和角色管理的 count 值变化。
可以看到菜单管理中当我们切换到其他页面再返回时,count 的值不会重新变为 0,而角色管理则会重置。到这里我们便完成了指定组件页面的缓存功能
源码地址 给个Star,么么哒!~