资讯专栏INFORMATION COLUMN

vue多级菜单(路由)导致缓存(keep-alive)失效

big_cat / 2571人阅读

摘要:造成这个问题的原因是多级路由组件嵌套。当点击菜单的时候,由于设置的不缓存,所以导致组件被销毁这就是为什么会失效的根本原因。既然这样的话,显示的菜单保留多级的,实际的弄成一级,将显示菜单和业务分离开。

一般的后台管理系统功能都比较繁多,存在有多级菜单的需求,但是在这种项目里往往keep-alive的表现却非常不稳定,有时候某个页面可以缓存,但是点几下就发现缓存丢了;有时候不知道怎么回事又死活不缓存了。

造成这个问题的原因是: 多级路由组件嵌套。
具体分析: 假如一个后台管理系统,有一个main.vue是所有页面的框架, 里面有这样一段代码

          
            
          
          

然后建立了一个父级菜单,页面是ChildView.vue, 里面的代码如下

假设这个父菜单里有两个子菜单,分别为 A和B, 然后A设置为缓存(keepAlive=true), B不缓存(keepAlive=false);
当点击A菜单的时候,系统缓存了ChildView.vue组件。
当点击B菜单的时候,由于B设置的不缓存,所以导致ChildView.vue组件被销毁
这就是keep-alive为什么会失效的根本原因。

还有更复杂的,比如同一个菜单里的子菜单可以缓存,但是点击另外一个父菜单或者父菜单下的子菜单却不缓存, 究其原理和上面的分析是一样的原因,就是多级菜单,多个共用组件导致的keepAlive缓存失效, keepAlive根本没考虑到页面缓存的复杂性。

以下几种表现也是这个问题造成的原因之一:

activated和deactivated不触发

从A页面进入B页面发现的时候发现A页面的接口又会被重复触发调用

分析问题:
既然是多个router-view嵌套并且共用的情况下造成的,那么如果只存在一个router-view,也就是只需要main.vue作为框架内所有页面的容器,就不会有这个问题。

实际上是不是多级菜单对于项目或者业务上来讲一点都不影响,只是界面显示上需要,让用户能更快点击到自己需要的功能页面而已。 既然这样的话,显示的菜单保留多级的,实际的router弄成一级, 将显示菜单和业务router分离开。

解决问题:
首先将配置好的多级router用vuex缓存起来,用作展示的菜单。
然后将router转换一下,转换成一级菜单,用addRoutes异步添加到router里面。

局部示例代码:

const formatRouter = (routes, newRoutes = []) => {
  routes.map(item => {
    if (item.children && item.children.length > 0) formatRouter(item.children, newRoutes);
    newRoutes.push(item);
  })
  return newRoutes;
}
let flatRoutes = formatRouter(routes);
router.addRoutes(flatRoutes);

然后面包屑导航要调整一下,大部分逻辑都是从route.matched里面获取的,但是现在router全是一级的,我们要从展示的菜单数据里面拿面包屑导航数据。

示例代码:

/**
 * 自定义查找字段, 根据最后一级某个字段查找完整树(整个父类)
 * @param {*} val     要查找对比的值
 * @param {*} data    要查找的数据
 * @param {*} fKey    要查找对比的字段
 */ 
const recursiveTreeByLastLevel = (val, data, fKey = "value") => {
  let rData = [];
  for (let i = 0, len = data.length; i < len; i++) {
    rData.push(data[i]);
    if (data[i].children && data[i].children.length > 0) {
      rData = rData.concat(recursiveTreeByLastLevel(val, data[i].children, fKey));
      if (rData.some(item => item[fKey] === val)) return rData;
    }
    if (data[i][fKey] === val) return rData;
    rData = [];
  }
  return rData;
}
 
router.afterEach((to, from, next) => {
  var routerList = recursiveTreeByLastLevel(to.name, store.state.sidebarMenu, "name")
  store.commit("setCrumbList", routerList) // 通过vuex缓存
})

搞完,收工!

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/106415.html

相关文章

  • vue keep-alive实现动态缓存以及缓存销毁

    摘要:实现动态缓存以及缓存销毁需求来源及描述后台管理系统中,左侧为功能菜单栏,点击菜单列表,右侧显示该菜单的功能页面,本来是一个非常简单的后台管理系统布局,现在增加了菜单按钮点击左侧菜单栏时,右侧页面头部显示当前的页面标题,形成一个列表,点击可 vue keep-alive实现动态缓存以及缓存销毁 需求来源及描述 后台管理系统中,左侧为功能菜单栏,点击菜单列表,右侧显示该菜单的功能页面,本来...

    littleGrow 评论0 收藏0
  • vue项目中keep-alive缓存,从详情页返回列表时保存上一步的信息

    摘要:问题由来最近用做前端项目,从查询页面进入详情页时,返回页面需要保留上次的查询条件,表格当前页数。从其他菜单进去,不需要缓存,要保持页面的初始状态。当进入详情页,需要对该条数据进行修改时,修改成功后返回,应该更新列表。 问题由来 1、最近用vue做前端项目,从查询页面进入详情页时,返回页面需要保留上次的查询条件,表格当前页数。2、从其他菜单进去,不需要缓存,要保持页面的初始状态。基于上面...

    justjavac 评论0 收藏0
  • vue轻量级后台管理系统基础模板

    摘要:具体实现请查看和的退出登陆回调方法。现在除了必要的页面需要在一开始添加到路由表里,其他的页面都可以根据后台数据来自动生成。另外,如果在未登陆时要访问某一指定页面,会重定向到登陆页,登陆成功后会自动跳到这个指定页面。 项目地址 vue-admin-template 在线预览 更新 2019.6.25 更新 修复路由表冲突问题 退出当前用户,换账号重新登陆时,上个账号和现在的账号路由表会有...

    2shou 评论0 收藏0
  • Vue+Express全栈购物商城

    摘要:一前言提纲基于和框架写的一个全栈购物商城,记录项目过程中遇到的一些问题以及经验和技巧。服务端技术栈登录授权用认证机制,来实现登录登出。服务器配置和缓存策略,根据不同的来代理。申请证书全站升级到,配置的协议。一、前言提纲 基于Vue和Express框架写的一个全栈购物商城,记录项目过程中遇到的一些问题以及经验和技巧。 二、历史版本 基于Vue-CLI2.0:点我查看 这个分支版本是一两年前...

    Richard_Gao 评论0 收藏0
  • Vue+Express全栈购物商城

    摘要:一前言提纲基于和框架写的一个全栈购物商城,记录项目过程中遇到的一些问题以及经验和技巧。服务端技术栈登录授权用认证机制,来实现登录登出。服务器配置和缓存策略,根据不同的来代理。申请证书全站升级到,配置的协议。 一、前言提纲 基于Vue和Express框架写的一个全栈购物商城,记录项目过程中遇到的一些问题以及经验和技巧。 二、历史版本 基于Vue-CLI2.0:点我查看这个分支版本是一两...

    luzhuqun 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<