最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

vue動(dòng)態(tài)菜單、動(dòng)態(tài)路由加載以及刷新踩坑實(shí)戰(zhàn)

 更新時(shí)間:2021年10月17日 16:18:42   作者:創(chuàng)業(yè)男生  
這篇文章主要給大家介紹了關(guān)于vue動(dòng)態(tài)菜單、動(dòng)態(tài)路由加載以及刷新踩坑的相關(guān)資料,踩的這些坑其實(shí)是挺常見的,大家可以看看,避免遇到的時(shí)候再踩到同樣的坑,需要的朋友可以參考下

需求:

從接口動(dòng)態(tài)獲取子菜單數(shù)據(jù) 動(dòng)態(tài)加載 要求只有展開才加載子菜單數(shù)據(jù) 支持刷新,頁(yè)面顯示正常

思路:

一開始比較亂,思路很多。想了很多

首先路由和菜單共用一個(gè)全局route, 數(shù)據(jù)的傳遞也是通過store的route, 然后要考慮的倆個(gè)點(diǎn)就是一個(gè)就是渲染菜單和加載路由,可以在導(dǎo)航首位里處理路由,處理刷新。

還有一個(gè)地方就是菜單組件里展開事件里面 重新生成菜單數(shù)據(jù),路由。大體思路差不多,做完就忘了..... 刷新的問題需要用本地緩存處理,之前一直緩存這個(gè)route 大數(shù)據(jù),但是這個(gè)localstore 緩存的只是字符串,不能緩存對(duì)象,這樣的話,菜單是出來了,動(dòng)態(tài)的路由404,因?yàn)閖son.parse 轉(zhuǎn)出來的對(duì)象 不是真實(shí)路由數(shù)據(jù),還需要單獨(dú)處理component 這個(gè)是個(gè)函數(shù)對(duì)象,
都是坑....所以之前走了點(diǎn)彎路,思路沒想好。

第二天,重新整理思路,想了下,為啥要緩存整個(gè)route對(duì)象,傻是不是,動(dòng)態(tài)的數(shù)據(jù)只是一部分,三級(jí)菜單...何不分開存儲(chǔ),本地存儲(chǔ)動(dòng)態(tài)菜單數(shù)據(jù),利用完整的路由模板,取出來的初始化路由對(duì)象,然后,循環(huán)菜單數(shù)據(jù),動(dòng)態(tài)設(shè)置children屬性,生成一個(gè)新的完整的路由對(duì)象,addRoute不是更好嗎
想到這里,整理下完整思路

【定義全局route對(duì)象】=> 【導(dǎo)航首位判斷刷新、初始化加載 store中route為空】=> 【初始化路由和菜單】=> 【菜單展開事件里面,請(qǐng)求接口,拿到子菜單數(shù)據(jù),localStore 存儲(chǔ)菜單數(shù)據(jù),更新路由】
還有一些小坑 比如重復(fù)路由、刷新404問題、刷新白屏、異步處理...

教訓(xùn):

問題肯定能解決,折騰幾天,最后才發(fā)現(xiàn)思路最重要

思路錯(cuò)誤,就是浪費(fèi)時(shí)間

先想好思路,完整的實(shí)現(xiàn)路線 先干什么后干什么 其中遇到技術(shù)難點(diǎn)再去百度

分享正文:

暴力貼代碼?。。。。。。。。。。。?!

全局定義store route對(duì)象 都會(huì),忽略

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: '首頁(yè)', 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 守衛(wèi)初始化,這里注釋掉
})

//路由重復(fù)的問題 解決
router.$addRoutes = (params) => {
  router.matcher = new Router({ // 重置路由規(guī)則
    scrollBehavior: () => ({
      y: 0
    })
  }).matcher
  router.addRoutes(params) // 添加路由
}

export default router
//監(jiān)聽路由守衛(wèi) 生成動(dòng)態(tài)路由
router.beforeEach((to, from, next) => {
  
  const routes = store.state.app.routes

  console.error('beforeEach 守衛(wèi)執(zhí)行了')

  //處理首次加載 刷新
  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()
})
/**
 * 更新三級(jí)子菜單 路由元數(shù)據(jù)
 */
export const updateIPChildRoutes = function(routes, path, children) {
    return setRouteArrayChildren(routes, path, children)
}

/**
 * 根據(jù)父菜單加載子菜單
 * @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
      } 
  
      //動(dòng)態(tài)添加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(`加載子菜單錯(cuò)誤`)
      }
    })
}
import { isArray, setRouteArrayChildren } from './tool'

// 設(shè)置路由緩存值
const localRouteKey = "LOCALROUTESET";

/**
 * currentPath: '' //當(dāng)前訪問的路由路徑
 * routeData: [], //存儲(chǔ)的完整路由數(shù)據(jù)(僅加載菜單可用)
 * asyncRouteData: [] //動(dòng)態(tài)的路由數(shù)據(jù)(生成新路由使用)
 * {
 *    parentKey //父級(jí)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);
}

/**
 * 本地緩存 轉(zhuǎn)化成路由元數(shù)據(jù)
 * @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
}
/**
 * 設(shè)置路由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)
      

      //動(dòng)態(tài)生成監(jiān)控三級(jí)菜單/路由
      const ipAddrKeys = []
      grafanaAddrs.forEach(
        addr => {
          if (addr.matchup) {
            ipAddrKeys.push(addr.key)
          }
        }
      )

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

         generateIPChildRoutes(path)
         .then(ipAddrs => {
           
          if (isArray(ipAddrs)) {

            //緩存動(dòng)態(tài)路由數(shù)據(jù)
            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])

          }
         })
      }
    }

其他代碼 不是核心的 不貼了

總結(jié)

到此這篇關(guān)于vue動(dòng)態(tài)菜單、動(dòng)態(tài)路由加載以及刷新踩坑的文章就介紹到這了,更多相關(guān)vue動(dòng)態(tài)菜單、動(dòng)態(tài)路由加載內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Vue拖動(dòng)截圖功能的簡(jiǎn)單實(shí)現(xiàn)方法

    Vue拖動(dòng)截圖功能的簡(jiǎn)單實(shí)現(xiàn)方法

    最近項(xiàng)目上要做一個(gè)車牌識(shí)別的功能,就需要做拖動(dòng)截圖功能了,因?yàn)榍岸问莢ue,所以下面這篇文章主要給大家介紹了關(guān)于Vue拖動(dòng)截圖功能的簡(jiǎn)單實(shí)現(xiàn)方法,需要的朋友可以參考下
    2021-07-07
  • Vue3 computed初始化獲取設(shè)置值實(shí)現(xiàn)示例

    Vue3 computed初始化獲取設(shè)置值實(shí)現(xiàn)示例

    這篇文章主要為大家介紹了Vue3 computed初始化以及獲取值設(shè)置值實(shí)現(xiàn)示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-10-10
  • 詳解vue-cli + webpack 多頁(yè)面實(shí)例應(yīng)用

    詳解vue-cli + webpack 多頁(yè)面實(shí)例應(yīng)用

    本篇文章主要介紹了詳解vue-cli + webpack 多頁(yè)面實(shí)例應(yīng)用,具有一定的參考價(jià)值,有興趣的可以了解一下
    2017-04-04
  • 常見的5種Vue組件通信方式總結(jié)

    常見的5種Vue組件通信方式總結(jié)

    在?Vue.js?中,組件通信是開發(fā)過程中非常重要的一部分,它涉及到不同組件之間的數(shù)據(jù)傳遞和交互,本文將介紹如何實(shí)現(xiàn)父子組件之間的有效通信,并盤點(diǎn)了常見的5種Vue組件通信方式總結(jié),需要的朋友可以參考下
    2024-03-03
  • Vue下拉框加分頁(yè)搜索功能的實(shí)現(xiàn)方法

    Vue下拉框加分頁(yè)搜索功能的實(shí)現(xiàn)方法

    開發(fā)任務(wù)中有這樣一個(gè)需求,下拉框中需要展示超過5000條數(shù)據(jù),甚至更多,這數(shù)據(jù)量直接整個(gè)頁(yè)面卡死了,就想到在下拉框中加分頁(yè),下面小編通過實(shí)例代碼介紹下Vue下拉框加分頁(yè)搜索功能的實(shí)現(xiàn),感興趣的朋友一起看看吧
    2022-11-11
  • 關(guān)于vue.extend的使用及說明

    關(guān)于vue.extend的使用及說明

    這篇文章主要介紹了關(guān)于vue.extend的使用及說明,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-03-03
  • Vue中watch與watchEffect的區(qū)別詳細(xì)解讀

    Vue中watch與watchEffect的區(qū)別詳細(xì)解讀

    這篇文章主要介紹了Vue中watch與watchEffect的區(qū)別詳細(xì)解讀,watch函數(shù)與watchEffect函數(shù)都是監(jiān)聽器,在寫法和用法上有一定區(qū)別,是同一功能的兩種不同形態(tài),底層都是一樣的,需要的朋友可以參考下
    2023-11-11
  • vue 輸入電話號(hào)碼自動(dòng)按3-4-4分割功能的實(shí)現(xiàn)代碼

    vue 輸入電話號(hào)碼自動(dòng)按3-4-4分割功能的實(shí)現(xiàn)代碼

    這篇文章主要介紹了vue 輸入電話號(hào)碼自動(dòng)按3-4-4分割功能的實(shí)現(xiàn)代碼,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-04-04
  • Vue $emit $refs子父組件間方法的調(diào)用實(shí)例

    Vue $emit $refs子父組件間方法的調(diào)用實(shí)例

    今天小編就為大家分享一篇Vue $emit $refs子父組件間方法的調(diào)用實(shí)例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧
    2018-09-09
  • Vue3 核心特性Suspense 與 Teleport 原理解析

    Vue3 核心特性Suspense 與 Teleport 原理解析

    本文詳細(xì)解析了Vue3的核心特性Suspense和Teleport,包括它們的實(shí)現(xiàn)原理、核心源碼、生命周期流程、依賴追蹤機(jī)制等,通過深入理解這兩個(gè)API的設(shè)計(jì)哲學(xué),開發(fā)者可以提升代碼組織能力、優(yōu)化應(yīng)用性能和實(shí)現(xiàn)更優(yōu)雅的架構(gòu)設(shè)計(jì),感興趣的朋友一起看看吧
    2025-03-03

最新評(píng)論

三原县| 东兰县| 琼海市| 成武县| 邹城市| 菏泽市| 镇远县| 新民市| 秦安县| 乳源| 上杭县| 磐安县| 肥乡县| 尉犁县| 木兰县| 古丈县| 镇平县| 县级市| 滁州市| 尤溪县| 灵宝市| 股票| 滦南县| 德令哈市| 克什克腾旗| 巍山| 禹城市| 读书| 阳西县| 陆良县| 南昌市| 赤水市| 梁河县| 桐乡市| 塔河县| 大足县| 玛纳斯县| 石首市| 横峰县| 眉山市| 海安县|