您当前的位置:首页 > 网站建设 > javascript
| php | asp | css | H5 | javascript | Mysql | Dreamweaver | Delphi | 网站维护 | 帝国cms | React | 考试系统 | ajax | jQuery | 小程序 |

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

51自学网 2022-02-21 13:39:42
  javascript

需求:

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

思路:

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

首先路由和菜单共用一个全局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动态菜单、动态路由加载内容请搜索51zixue.net以前的文章或继续浏览下面的相关文章希望大家以后多多支持51zixue.net!


下载地址:
vue3如何使用provide实现状态管理详解
微信小程序实现短信登录的实战
万事OK自学网:51自学网_软件自学网_CAD自学网自学excel、自学PS、自学CAD、自学C语言、自学css3实例,是一个通过网络自主学习工作技能的自学平台,网友喜欢的软件自学网站。