解决vue项目中keep-alive不能缓存多层级路由问题

解决vue项目中keep-alive不能缓存多层级路由问题

看了很多文档,都是把嵌套多级路由简化(keep-alive满足二级/一级菜单缓存),菜单数据和路有数据分离开,这种方案解决起来相对复杂一些,下面的方法相对简单一些,我是看了这篇文章,结合自己的项目稍作修改.下边也有自己遇到的问题及解决方法.

需求介绍

自己项目的图片不便粘贴,我还是引用原博主的图片
在这里插入图片描述
项目中使用的是3级路由,要实现三级菜单来回跳转保存状态(并且跨二级菜单间的三级菜单页面切换也需要保存状态)
咱们首先想到的是使用keep-alive标签来实现此功能.
在3级router-view的index.vue文件添加keep-alive标签

<template>
  <div>
    <keep-alive :include="tagNames">
      <router-view v-if="$route.meta.keepAlive"></router-view>
    </keep-alive>
    <router-view v-if="!$route.meta.keepAlive"></router-view>
  </div>
</template>

<script>
import { mapGetters } from "vuex";
export default {
  name: "Blank",
  computed: {
    ...mapGetters("history", ["tagNames"]),
  },
};
</script>
<style lang="scss"></style>

这样只能实现二级菜单内三级菜单页面切换状态可以保存,跨二级菜单间的三级菜单页面切换也需要保存状态是不能实现的.

解决方案

1.把含有3级router-view的文件改为
<template>
    <router-view />
</template>
<script>
export default {
  name: 'Blank'
}
</script>
2.把之前3级router-view的index.vue中keep-alive展示逻辑,包括:include="tagNames"属性逻辑,都写到2级router-view的vue文件中,在我的项目中此文件为layout文件夹中index.vue,layout为项目中的整体布局文件.代码如下
<transition mode="out-in" name="el-fade-in-linear">
          <keep-alive :include="tagNames">
            <router-view
              v-loading="loadingFlag"
              element-loading-text="正在加载中"
              id="admin-box"
              class="admin-box"
              v-if="$route.meta.keepAlive"
            ></router-view>
          </keep-alive>
        </transition>
        <transition mode="out-in" name="el-fade-in-linear">
          <router-view
            v-loading="loadingFlag"
            element-loading-text="正在加载中"
            id="admin-box"
            class="admin-box"
            v-if="!$route.meta.keepAlive"
          ></router-view>
        </transition>
computed: {
    ...mapGetters("history", ["tagNames"]),
 },
3.在全局路由守卫中加上这段代码:(仅仅只是满足三级菜单缓存)

在这里插入图片描述

if (to.matched && to.matched.length > 2) {
   for (let i = 0; i < to.matched.length; i++) {
     const element = to.matched[i]
     if (element.components.default.name === 'Blank') {
       to.matched.splice(i, 1)
     }
   }
 }

我按照这种方案实现的时候,出现了两个问题
1.刷新页面后,首次切换页面并没有保存状态,切换后再回来操作才能保存.
2.如果页面中存在面包屑,由于把路由层级splice删掉的一级,导致面包屑层级有问题.

分析

问题1:在页面刷新的时候element.components.default.name是空值,导致to.matched.splice(i, 1)语句不执行.具体什么原因导致的,我没有深究,以后有人发现是啥导致的,可以留言给我.
问题2:由于把路由层级splice删掉的一级,我项目中面包屑正好是用to.matched路由层级遍历生成的所以出现了问题

思路

解决问题1
用数组存放需要保存功能的二级页面名称,只要三级路由结构的路由中含有这些名称,就把三级路由结构中的二级路由手动删除.
解决问题2
在删减层级之前把路由层级保存起来,用于面包屑的展示
直接上代码


router.beforeEach(async(to, from, next) => {
.........
//缓存中保存原有的3级路由title值存入缓存,用于面包屑路径显示(解决问题2)
    let matchedRouter = ["controlManagement","...."]      //存放需要保存功能的页面名称,这个地方按照你的项目中二级路由页面名称来确定
    for (let i = 0; i < to.matched.length; i++) {
        const element = to.matched[i]
        matchedRouter.push(element.meta.title)
    }
    sessionStorage.setItem("matchedRouter",JSON.stringify(matchedRouter)) 
    //修复三级路由不能保存状态问题(解决问题1)
    if (to.matched && to.matched.length > 2) {
        for (let i = 0; i < to.matched.length; i++) {
            const element = to.matched[i]
            const Index = saveBlankPages.findIndex((item) => {return item === element.name})
            if (Index>=0) {
                to.matched.splice(i, 1)
            }
        }
    }
    ..........

面包屑代码

<el-breadcrumb
  class="breadcrumb"
  separator-class="el-icon-arrow-right"
>
  <el-breadcrumb-item
    :key="item.path"
    v-for="item in matchedRouter.slice(1, matchedRouter.length)"
    >{
   
   { item }}</el-breadcrumb-item
  >
</el-breadcrumb>
watch: {
    $route(){
      let matchedRouter = JSON.parse(sessionStorage.getItem("matchedRouter"))
      this.matchedRouter = matchedRouter;
    }
  },

希望对你有帮助

猜你喜欢

转载自blog.csdn.net/weixin_46995731/article/details/123665776
今日推荐