vue動態選單、動態路由載入以及重新整理踩坑實戰
目錄
- 需求:
- 思路:
- 教訓:
- 分享正文:
- 總結
需求:
從介面動態獲取子選單資料 動態載入 要求只有展開才載入子選單資料 支援重新整理,頁面顯示正常
思路:
一開始比較亂,思路很多。想了很多
首先路由和選單共用一個全域性route,資料的傳遞也是通過store的route,然後要考慮的倆個點就是一個就是渲染選單和載入路由,可以在導航首位裡處理路由,處理重新整理。
還有一個地方就是選單元件裡展開事件裡面 重新生成選單資料,路由。大體思路差不多,做完就忘了..... 重新整理的問題需要用本地快取處理,之前一直快取這個route 大資料,但是這個localstore 快取的只是字串,不能快取物件,這樣的話,選單是出來了,動態的路由404,因為on.parse 轉出來的物件 不是真實路由資料,還需要單獨處理component 這個是個函式物件,
第二天,重新整理思路,想了下,為啥要快取整個route物件,傻是不是,動態的資料只是一部分,三級選單...何不分開儲存,本地儲存動態選單資料,利用完整的路由模板,取出來的初始化路由物件,然後,迴圈選單資料,動態設定children屬性,生成一個新的完整的路由物件,addRoute不是更好嗎
想到這裡,整理下完整思路
【定義全域性route物件】=> 【導航首位判斷重新整理、初始化載入 swww.cppcns.comtore中route為空】=> 【初始化路由和選單】=> 【選單展開事件裡面,請求介面,拿到子選單資料,localStore 儲存選單資料,更新路由】
教訓:
問題肯定能解決,折騰幾天,最後才發現思路最重要
思路錯誤,就是浪費時間
先想好思路,完整的實現路線 先幹什麼後幹什麼 其中遇到技術難點再去百度
分享正文:
暴力貼程式碼!!!!!!!!!!!!!
全域性定義store route物件 都會,忽略
import 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'),{ 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,key: 'control' },children: [] },{ path: 'signal',www.cppcns.comname: 'signal',key: 'signal',children: [] },{ path: 'gateway',name: 'gateway',key: 'gateway' },children: [] } ] },{ path: 'meeting',name: 'meting',www.cppcns.com 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,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,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,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,ipAddrs) store .dispatch('app/setRoutes',asyncRoutes) router.$addRoutes([...asyncRoutes]) } }) } }
其他程式碼 不是核心的 不貼了
總結
到此這篇關於vue動態選單、動態路由載入以及重新整理踩坑的文章就介紹到這了,更多相關vue動態選單、動態路由載入內容請搜尋我們以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援我們!