iis服务器助手广告广告
返回顶部
首页 > 资讯 > 前端开发 > JavaScript >vue动态菜单、动态路由加载以及刷新踩坑实战
  • 256
分享到

vue动态菜单、动态路由加载以及刷新踩坑实战

2024-04-02 19:04:59 256人浏览 独家记忆
摘要

目录需求:思路:教训:分享正文:总结需求: 从接口动态获取子菜单数据 动态加载 要求只有展开才加载子菜单数据 支持刷新,页面显示正常 思路: 一开始比较乱,思路很多。想了很多 首先

需求:

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

思路:

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

首先路由和菜单共用一个全局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)
}


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";



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);
}


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
}


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动态菜单、动态路由加载内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

--结束END--

本文标题: vue动态菜单、动态路由加载以及刷新踩坑实战

本文链接: https://www.lsjlt.com/news/154639.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • vue动态菜单、动态路由加载以及刷新踩坑实战
    目录需求:思路:教训:分享正文:总结需求: 从接口动态获取子菜单数据 动态加载 要求只有展开才加载子菜单数据 支持刷新,页面显示正常 思路: 一开始比较乱,思路很多。想了很多 首先...
    99+
    2022-11-12
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作