首页 > 其他分享 >vue-element-admin/litemall后端,超过两级嵌套路由无法缓存的问题

vue-element-admin/litemall后端,超过两级嵌套路由无法缓存的问题

时间:2024-01-17 17:22:57浏览次数:27  
标签:vue admin element item meta path children 路由 matched

本文主要针对的是litemall后端,vue-element-admin只需稍作修改应该也可以适用。路由扁平的思路主要来源于https://blog.csdn.net/weixin_40119256/article/details/111475571,另外解决面包屑显示问题,此文章作记录以供有需要的同行参考。

keep-alive 用于缓存不活跃的组件实例,避免重复渲染和重新创建组件实例。然而,keep-alive 只能缓存其内部的最外层组件,对于嵌套的子组件,keep-alive 无法直接缓存。vue router的第一层是Layout component,如果二级路由是页面则keep-alive自然可以缓存。但是如果嵌套路由超过了两级,则必然会在页面上层至少套上了一层以上的component,keep-alive无法直接缓存,这就是本文要解决的问题。

把路由变成二级的扁平化

  • 更新文件./src/store/modules/permission.js

添加获取扁平化路由表的方法。跟参考文章不一样的地方是,我这里的path只需保留最后的两级。不然无法跟litemall的页面路由匹配。如原来path是/A/B/C,这里会变成/B/C。

另外修复源代码的bug,castToFlatRoute(item.children, ’‘)修改为castToFlatRoute(item.children, item.path)。如果存在一个二级菜单,生成的path会缺失父级的path。

/**  * 生成扁平化机构路由(仅两级结构)  * @param {允许访问的路由Tree} accessRoutes  * 路由基本机构:  * {  *   name: String,  *   path: String,  *   component: Component,  *   redirect: String,  *   children: [  *   ]  * }  */ function generateFlatRoutes(accessRoutes) {   const flatRoutes = []
  for (const item of accessRoutes) {     let childrenFflatRoutes = []     if (item.children && item.children.length > 0) {       childrenFflatRoutes = castToFlatRoute(item.children, item.path)     }
    // 一级路由是布局路由,需要处理的只是其子路由数据     flatRoutes.push({       name: item.name,       path: item.path,       component: item.component,       redirect: item.redirect,       meta: item.meta,       children: childrenFflatRoutes     })   }
  return flatRoutes }
/**    * 将子路由转换为扁平化路由数组(仅一级)    * @param {待转换的子路由数组} routes    * @param {父级路由路径} parentPath    */ function castToFlatRoute(routes, parentPath, flatRoutes = []) {   for (const item of routes) {     if (item.name === 'approval-management') {       debugger     }     // remove the '/' if item start with '/'     let newPath = parentPath + '/' + item.path     if (item.path.substring(0, 1) === '/') {       newPath = parentPath + item.path     }     // keep that last 2 parts only     const pathParts = newPath.split('/')     if (pathParts.length > 3) {       newPath = '/' + pathParts[pathParts.length - 2] + '/' + pathParts[pathParts.length - 1]     }
    if (item.children && item.children.length > 0) {       if (item.redirect && item.redirect !== 'noredirect') {         flatRoutes.push({           name: item.name,           path: newPath,           redirect: item.redirect,           meta: item.meta         })       }       castToFlatRoute(item.children, newPath, flatRoutes)     } else {       flatRoutes.push({         name: item.name,         path: newPath,         component: item.component,         meta: item.meta       })     }   }
  return flatRoutes }

更新GenerateRoutes()方法返回扁平后的路由表。注意不要动原有的这句”commit('SET_ROUTERS', accessedRouters)“。

const flatRoutes = generateFlatRoutes(accessedRouters)
resolve(flatRoutes)

 

更新Router

  • 更新文件./src/permission.js

用router.addRoutes(flatRoutes)替换router.addRoutes(store.getters.addRouters)。

store
  .dispatch('GetUserInfo', getUserToken())
  .then(res => {
    // 拉取user_info
    const perms = store.getters.perms // note: perms must be a array! such as: ['GET /aaa','POST /bbb']
    store
      .dispatch('GenerateRoutes', {
        perms
      })
      .then((flatRoutes) => {
        // flat routes to fix the issue of keep alive cannot cache nested component
        router.addRoutes(flatRoutes)

        // 根据perms权限生成可访问的路由表
        // router.addRoutes(store.getters.addRouters) // 动态添加可访问路由表
        next({
          ...to,
          replace: true
        }) // hack方法 确保addRoutes已完成 ,set the replace: true so the navigation will not leave a history record
      })
  })
  .catch(err => {
    store.dispatch('FedLogOut').then(() => {
      Message.error(err || 'Verification failed, please login again')
      next({
        path: '/'
      })
    })
  })

 

解决面包屑显示问题

  • 更新文件./src/store/modules/permission.js

在原有的route上添加matched信息。

/**
 * add matched for breadcrumb display
 * @param routes routes list
 * @returns routers
 */
function addBreadcrumb(routes, matched = []) {
  const res = []
  routes.forEach(route => {
    const tmp = {
      ...route
    }
    const tmpMatched = [
      ...matched
    ]
    tmpMatched.push({
      meta: (tmp.meta ? tmp.meta : undefined),
      redirect: tmp.redirect,
      path: (tmp.path ? tmp.path : '/') })

    if (tmp.children) {
      tmp.children = addBreadcrumb(tmp.children, tmpMatched)
      if (tmp.children && tmp.children.length > 0) {
        tmp.matched = tmpMatched
        res.push(tmp)
      }
    } else {
      tmp.matched = tmpMatched
      res.push(tmp)
    }
  })
  return res
}

更新GenerateRoutes()方法在保存之前添加matched信息。

if (perms.includes('*')) {
  accessedRouters = addBreadcrumb(asyncRouterMap)
} else {
  accessedRouters = addBreadcrumb(filterAsyncRouter(asyncRouterMap, perms))
}
  •  更新文件./src/components/Breadcrumb/index

添加getMatchRoute()用于查找匹配的路由。

getMatchRoute(routers, targetName) {
  for (let k = 0; k < routers.length; k++) {
    const route = routers[k]
    if (route.children && route.children.length > 0) {
      const matched = this.getMatchRoute(route.children, targetName)
      if (matched !== undefined) {
        return matched
      }
    } else if (route.name === targetName) {
      return route
    }
  }
},

添加属性fullRoute用于保存包含面包屑信息的匹配的路由条目。更新getBreadcrumb()根据匹配的路由生成面包屑。

getBreadcrumb() {
  this.fullRoute = this.getMatchRoute(store.getters.addRouters, this.$route.name)
  if (!this.fullRoute) {
    this.fullRoute = this.$route
  }

  // only show routes with meta.title
  let matched = this.fullRoute.matched.filter(
    item => item.meta && item.meta.title
  )
  const first = matched[0]
  if (!this.isDashboard(first)) {
    matched = [{ path: '/home', meta: { title: 'Home' }}].concat(matched)
  }
  this.levelList = matched.filter(
    item => item.meta && item.meta.title && item.meta.breadcrumb !== false
  )
},

更新pathCompile(),生成链接。

pathCompile(path) {
  // To solve this problem https://github.com/PanJiaChen/vue-element-admin/issues/561
  const { params } = this.fullRoute
  var toPath = pathToRegexp.compile(path)
  return toPath(params)
},

 

注意:如果要启用页面缓存,必须保证路由的name跟component的name一模一样。

 

参考:

https://blog.csdn.net/weixin_40119256/article/details/111475571

 

转载请注明出处:https://www.cnblogs.com/keitsi/p/17969846

标签:vue,admin,element,item,meta,path,children,路由,matched
From: https://www.cnblogs.com/keitsi/p/17969846

相关文章

  • vue-element-admin关闭标签跳转到前一个标签,而不是最近的标签
    vue-element-admin中关闭标签跳转到前一个标签,而不是最近的标签。场景:先后打开A和B标签,接着从A标签页面内部跳转到C标签(A和C存在紧密关系)。这时如果关闭C标签,默认跳转到最近的B标签而不是A标签。如果A和C中间隔着很多标签,这种场景很难在找回A标签的位置。期望跳转时从A跳转到C处......
  • 你不知道的vue3:使用runWithContext实现在非 setup 期间使用inject
    前言日常开发时有些特殊的场景需要在非setup期间调用inject函数,比如app中使用provide注入的配置信息需要在发送http请求时带上传给后端。对此我们希望不在每个发起请求的地方去修改,而是在发起请求前的拦截进行统一处理,对此我们就需要在拦截请求的函数中使用inject拿到app注入的......
  • 几种常见的注册登录验证(vue)
    几种常见的注册登录验证(vue):https://mp.weixin.qq.com/s?__biz=MzUzMTMxODY3OQ==&mid=2247493893&idx=1&sn=687cac339a3350c548043e069b9db1ac&chksm=fa46fbfdcd3172eb45e49a1b563e47f048224653ecb9c50957e38eedb0a67e0d17ca3207aa66&mpshare=1&scene=23&s......
  • vue-types
    一、vue-typesVueTypes是Vue.js的可配置prop验证器的集合,受到React的启发prop-types1、何时使用​虽然Vue.js中的基本prop验证既简单又方便,但细粒度验证在复杂组件上可能会变得冗长。VueTypes提供了一个紧凑而流畅的界面来定义项目的props。 2、使用示例​想......
  • Vuex的简单理解和使用
    1、什么是Vuex?在使用vue作为框架的前端项目开发中,我们经常会碰到Vuex,那么Vuex到底是什么东西呢?根据官方文档给出的解释是:Vuex是一个专为Vue.js应用程序开发的状态管理模式+库。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。简......
  • 基于SpringBoot+Vue的校园招聘系统设计实现(源码+lw+部署文档+讲解等)
    (文章目录)前言:heartpulse:博主介绍:✌全网粉丝10W+,CSDN特邀作者、博客专家、CSDN新星计划导师、全栈领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战✌:heartpulse:......
  • Vue的优化
    Vue前端开发到第一阶段,就要开始考虑性能优化相关的要点了。这也是用来判断一名前端的水平是否优秀的一个标准。接下来这篇文章,将介绍几种在实践过程中可以用到的性能优化技巧函数型组件由于组件的生命周期处理在框架层面上十分耗时,所以,建议平常尽量使用函数型组件。这样,可以避免不......
  • Vue学习计划-Vue3--核心语法(六)路由
    1.路由【对路由的理解】【基本切换效果】Vue3中要使用vue-router的最新版本,目前是4版本路由配置文件代码如下://创建一个路由器,并暴露出去//第一步:引入createRouterimport{createRouter,createWebHistory}from'vue-router'//引入一个一个可能要呈现组件......
  • Elementui中el-tree获取节点的选中、设置节点的选中
    this.$refs.tree.getCheckedNodes()//返回的是数组,包含所有选中的节点,不只是叶子节点。this.$refs.tree.setCheckedKeys(ids)//传递的是叶子节点的id合集例子:/***节点被点击时的回调*@paramdata-传递给data属性的数组中该节点所对应的对象*/nodeClick(data){c......
  • 【源码系列#06】Vue3 Diff算法
    专栏分享:vue2源码专栏,vue3源码专栏,vuerouter源码专栏,玩具项目专栏,硬核......