目录

需求:

从接口动态获取子菜单数据 动态加载 要求只有展开才加载子菜单数据 支持刷新,页面显示正常

思路:

一开始比较乱,思路很多。想了很多

首先路由和菜单共用一个全局route, 数据的传递也是通过store的route, 然后要考虑的俩个点就是一个就是渲染菜单和加载路由,可以在导航首位里处理路由,处理刷新。

还有一个地方就是菜单组件里展开事件里面 重新生成菜单数据,路由。大体思路差不多,做完就忘了….. 刷新的问题需要用本地缓存处理,之前一直缓存这个route 大数据,但是这个localstore 缓存的只是字符串,不能缓存对象,这样的话,菜单是出来了,动态的路由404,因为json.parse 转出来的对象 不是真实路由数据,还需要单独处理component 这个是个函数对象,
都是坑….所以之前走了点弯路,思路没想好。

第二天,重新整理思路,想了下,为啥要缓存整个route对象,傻是不是,动态的数据只是一部分,三级菜单…何不分开存储,本地存储动态菜单数据,利用完整的路由模板,取出来的初始化路由对象,然后,循环菜单数据,动态设置children属性,生成一个新的完整的路由对象,addroute不是更好吗
想到这里,整理下完整思路

【定义全局route对象】=> 【导航首位判断刷新、初始化加载 store中route为空】=> 【初始化路由和菜单】=> 【菜单展开事件里面,请求接口,拿到子菜单数据,localstore 存储菜单数据,更新路由】
还有一些小坑 比如重复路由、刷新404问题、刷新白屏、异步处理…

教训:

问题肯定能解决,折腾几天,最后才发现思路最重要

思路错误,就是浪费时间

先想好思路,完整的实现路线 先干什么后干什么 其中遇到技术难点再去百度

分享正文:

暴力贴代码!!!!!!!!!!!!!

全局定义store route对象 都会,忽略

import vue from 'vue'
import router from 'vue-router'
import layout from '@/layout'

vue.use(router)

export const constantroutes = [{
  path: '/login',
  name: 'login',
  component: () => import('@/views/login/index'),
  hidden: true,
}, {
  path: '/404',
  name: '404',
  component: () => import('@/views/error-page/404'),
  hidden: true
}, {
  path: '/401',
  name: '401',
  component: () => import('@/views/error-page/401'),
  hidden: true
}, {
  path: '/',
  component: layout,
  redirect: '/dashboard',
  children: [
    {
      path: 'dashboard',
      component: () => import('@/views/dashboard/index'),
      name: 'dashboard',
      meta: { title: '首页', icon: 'documentation' }
    },
    {
      path: 'xxx',
      component: () => import('xxxxx'),
      name: 'xxx',
      meta: { title: 'xxx', icon: 'component' },
      children: [
          {
            path: 'host',
            name: 'host',
            meta: { 
              title: 'xxx', 
              key: 'host'
            }
          },
          {
            path: 'control',
            name: 'control',
            alwaysshow: true,
            meta: { 
              title: 'xxx', 
              key: 'control'
            },
            children: []
          },
          {
            path: 'signal',
            name: 'signal',
            alwaysshow: true,
            meta: { 
              title: 'xxx', 
              key: 'signal',
            },
            children: [] 
          },
          {
            path: 'gateway',
            name: 'gateway',
            alwaysshow: true,
            meta: { 
              title: 'xxx', 
              key: 'gateway'
            },
            children: []
          } 
      ]
    },
    {
      path: 'meeting',
      name: 'meting',
      meta: { title: 'xxx', icon: 'list' }
    },
    {
      path: 'traces',
      component: () => import('@/views/xxx'),
      name: 'traces',
      meta: { title: 'xxx', icon: 'chart' }
    }
]
}, 
  {
    path: '*',
    redirect: '/404',
    hidden: true
  }
]

const router = new router({
  // mode: 'history', // require service support
  scrollbehavior: () => ({
    y: 0
  }),
  //routes: constantroutes 守卫初始化,这里注释掉
})

//路由重复的问题 解决
router.$addroutes = (params) => {
  router.matcher = new router({ // 重置路由规则
    scrollbehavior: () => ({
      y: 0
    })
  }).matcher
  router.addroutes(params) // 添加路由
}

export default router
//监听路由守卫 生成动态路由
router.beforeeach((to, from, next) => {
  
  const routes = store.state.app.routes

  console.error('beforeeach 守卫执行了')

  //处理首次加载 刷新
  if(routes.length === 0){
     console.error('首次/刷新了')

     //更新路由缓存
     const cacheroute = getlocalrouteinfo()
     
     const routevalue = asyncroutedatatoroute(cacheroute.asyncroutedata, constantroutes)
     
     store
      .dispatch('app/setroutes', routevalue)

     router.$addroutes([...routevalue])

     next({
        ...to,
        replace: true
     })
     return
   } 

   next()
})
/**
 * 更新三级子菜单 路由元数据
 */
export const updateipchildroutes = function(routes, path, children) {
    return setroutearraychildren(routes, path, children)
}

/**
 * 根据父菜单加载子菜单
 * @param {*} routekey 
 * @returns 
 */
export const generateipchildroutes =  function(routekey) {
    return new promise((resolve, reject) => {
      if (!routekey) return
      
      
      // const start = getdateseconds(new date())
      // const end = setdateseconds(new date(), 15, 'm')
      
      const filteraddr = grafanaaddrs.filter(addr => addr.key === routekey)[0]
      const matchup = filteraddr.matchup
  
      const params = {
        matchup
      } 
  
      //动态添加routers
      try {
        fetchipinstance(params).then(ipaddrs => {
          const iproutes = []
          ipaddrs.foreach(
            addr => {
                const ipinstance = addr.instance.replace(/^(.*):.*$/, "$1")
  
                if(!isipaddress(ipinstance)) 
                  return
  
                const existroute = iproutes.find(ip => ip.meta && ip.meta.key === ipinstance)
  
                !existroute && iproutes.push(
                  {
                    path: ipinstance,
                    name: ipinstance,
                    meta: { 
                        title: ipinstance, 
                        key: ipinstance
                    }
                  }
                )
            }
          )
          resolve(iproutes)
        })
      } catch (error) {
        reject(error)
        console.error(`加载子菜单错误`)
      }
    })
}
import { isarray, setroutearraychildren } from './tool'

// 设置路由缓存值
const localroutekey = "localrouteset";

/**
 * currentpath: '' //当前访问的路由路径
 * routedata: [], //存储的完整路由数据(仅加载菜单可用)
 * asyncroutedata: [] //动态的路由数据(生成新路由使用)
 * {
 *    parentkey //父级key
 *    route: [
 *      {
            path: ,
            name: ,
            meta: { 
                title: , 
                key: 
            }
        }
 *    ]
 * }
 */

export function getlocalrouteinfo() {
  const data = localstorage.getitem(localroutekey);

  return data ? json.parse(data) : {};
}

export function setlocalrouteinfo(data) {
  const localdata = getlocalrouteinfo();

  localstorage.setitem(
    localroutekey,
    json.stringify({
      ...localdata,
      ...data,
    })
  );
}

export function removelocalrouteinfo() {
  localstorage.removeitem(localroutekey);
}

/**
 * 本地缓存 转化成路由元数据
 * @param {*} constantroutes 路由模板
 */
export function asyncroutedatatoroute(asyncroutedata, constantroutes) {
   let route = constantroutes
   if (isarray(asyncroutedata) && asyncroutedata.length > 0) {
     asyncroutedata.foreach(
        data => {
          route = setroutearraychildren(route, data.parentkey, data.route)
        }
     )
   }
   return route
}
/**
 * 设置路由children属性
 * @param {*} routes 
 * @param {*} path 
 * @param {*} children 
 * @returns 
 */
export const setroutearraychildren = function(routes, path, children) {

  if (!isarray(routes) || !path)
     return new array()
  
  for (const route of routes) {
    if (isarray(route.children)) {
      if (route.path === path && route.children.length === 0) {
        route.children.push(...children)
      } else {
        setroutearraychildren(route.children, path, children)
      }
    }
  }

  return routes
}
onexpandmenu(key, keypath) {
      console.error(key, keypath)

      const path = key.substring(key.lastindexof('/') + 1)
      console.error(path)
      

      //动态生成监控三级菜单/路由
      const ipaddrkeys = []
      grafanaaddrs.foreach(
        addr => {
          if (addr.matchup) {
            ipaddrkeys.push(addr.key)
          }
        }
      )

      if (path && ipaddrkeys.includes(path)) {

         generateipchildroutes(path)
         .then(ipaddrs => {
           
          if (isarray(ipaddrs)) {

            //缓存动态路由数据
            const localrouteinfo = getlocalrouteinfo()
            const cacheroutes = localrouteinfo.asyncroutedata || []
            cacheroutes.push(
                {
                    parentkey: path,
                    route: ipaddrs
                }
              )
            setlocalrouteinfo({
              asyncroutedata : cacheroutes
            })

            //更新route
            let asyncroutes = store.state.app.routes

            asyncroutes = updateipchildroutes(asyncroutes, path, ipaddrs)
            
            store
              .dispatch('app/setroutes', asyncroutes)
            
            router.$addroutes([...asyncroutes])

          }
         })
      }
    }

其他代码 不是核心的 不贴了

总结

到此这篇关于vue动态菜单、动态路由加载以及刷新踩坑的文章就介绍到这了,更多相关vue动态菜单、动态路由加载内容请搜索www.887551.com以前的文章或继续浏览下面的相关文章希望大家以后多多支持www.887551.com!