vue组件keepAlive不生效
遇到的问题
问题描述
有一个后台管理项目,页面中实现了多选项卡切换功能,但是在多个选项卡之间切换的时候,每次页面都会重置,无法保持当前页面的状态。比如在页面一中筛选了某一列表的数据,再切换到其他页面再切换回来的时候,页面一中的筛选内容都会重置,影响用户的使用体验。
排查解决问题
-
排查
<keep-alive>标签的位置,以vue-element-admin为例,<keep-alive>标签位于 layout 布局中,也就是说加载到布局中的下一级的组件,能够保持状态。如果路由嵌套大于 2 级,那么就需要将<keep-alive>加到 layout 下级的组件中。 -
看看当前代码的写法是否正确,并且需要结合当前 vue 的版本和 vue-router 的版本来看。示例(vue3):
<!-- 错误写法 -->
<template>
<keep-alive>
<router-view v-slot="{ Component }">
<component :is="Component" />
</router-view>
</keep-alive>
</template>
<!-- 正确写法 -->
<template>
<router-view v-slot="{ Component }">
<keep-alive>
<component :is="Component" />
</keep-alive>
</router-view>
</template>
补充
通过上面代码在页面中实现多个选项卡组件状态缓存之后,出现另外一个组件复用的问题。比如要展示一个商品详情页,用的是同一个组件但是传入的商品id不一样,因为组件的name是固定的,所以切换不同商品详情页面时页面不刷新。
解决办法:在组件中指定一个key,这个key的值就是当前页面的fullPath,当key改变的时候,组件就会强制刷新。
<template>
<router-view v-slot="{ Component }">
<keep-alive :include="cachedViews" :max="30">
<component :is="Component" :key="key" />
</keep-alive>
</router-view>
</template>
<script>
export default {
name: "MainPage",
computed: {
cachedViews() {
return this.$store.state.tagsView.cachedViews;
},
key() {
return this.$route.fullPath;
},
},
};
</script>
keepAlive 使用方法
简介
<KeepAlive> 是一个内置组件,它的功能是在多个组件间动态切换时缓存被移除的组件实例。
基本用法
<!-- 切换组件时,包含在keep-alive标签中的组件状态会保存 -->
<template>
<keep-alive>
<component :is="name"></component>
</keep-alive>
</template>
配合路由实现页面多选项卡状态保持
<!-- 核心代码 -->
<template>
<router-view v-slot="{ Component }">
<keep-alive>
<component :is="Component" />
</keep-alive>
</router-view>
</template>
延申:vue 中的路由
import { createRouter, createWebHashHistory } from "vue-router";
import Layout from "../layout";
const routes = [
{
path: "/",
name: "Home",
/* 渲染到第一级<router-view /> 标签中,通常是App.vue */
component: Layout,
redirect: "/index",
meta: {
title: "首页",
},
children: [
{
path: "index",
name: "HomePage",
/* 渲染到父级组件的<router-view />标签中,也就是Layout中,所有子级路由以此类推 */
component: () => import("../views/Home.vue"),
meta: {
title: "首页",
},
},
{
path: "pageA",
name: "PageA",
component: () => import("../views/PageA.vue"),
meta: {
title: "页面A",
},
},
{
path: "pageB",
name: "PageB",
component: () => import("../views/PageB.vue"),
meta: {
title: "页面B",
},
},
],
},
];
const router = createRouter({
//history: createWebHistory(),
history: createWebHashHistory(),
routes,
});
export default router;