天天看點

iview admin動态路由設計思路開始改造其他唠嗑發現BUG了FK還是有BUG

感謝這篇文章:https://blog.csdn.net/weixin_34179968/article/details/92579951

網上找到了好多文章就這篇靠譜點,隻少能靠這篇文章把功能做出來。唯一缺點就是提供的代碼沒有後端,程式跑不起來。不過還好,有代碼參考也不錯。

這裡我不得不吐槽一下網上有的文章,太TMD坑,甚至還有故意留坑讓你自己去排查的,心中簡直就是萬馬奔騰的趕腳~

設計思路

  1. 通過改造擷取使用者資訊接口,有使用者資訊接口提供使用者資訊和菜單權限,并将菜單權限存到本地(user.js檔案改造)
  2. 改造本地路由(router.js檔案改造)
  3. 添加菜單解析方法(util.js添加方法)

    就這麼簡單,隻需要這三步就行了,不知道網上的怎本寫的那麼複雜。

開始改造

1、将擷取到的菜單存到本地緩存(user.js改造),使用者登入成功後将菜單存到本地
引入localSave方法
iview admin動态路由設計思路開始改造其他唠嗑發現BUG了FK還是有BUG
将資料存到本緩存(這個資料是由後端傳回的,你可以先直接寫個死資料在這)
iview admin動态路由設計思路開始改造其他唠嗑發現BUG了FK還是有BUG
如果你還沒開始對接後端的話,那就直接考下面代碼替換黃色的部分即可
var menus = [  {
              path: '',
              name: 'doc',
              meta: {
                access: ['超級管理者'],
                title: '文檔',
                href: 'https://lison16.github.io/iview-admin-doc/#/',
                icon: 'ios-book'
              }
            },
            {
              path: '/join',
              name: 'join',
              component: 'components/main',//注意,這一步很重要Main必須這樣替換掉
              children: [
                {
                  path: 'join_page',
                  name: 'join_page',
                  meta: {
                    icon: '_qq',
                    title: 'QQ群'
                  },
                  component: 'view/join-page.vue'
                }
              ]
            }];

            //将菜單存到本地
            localSave('userRouters',JSON.stringify(menus))
           
2、router.js改造
1、引入localRead和backendMenusToRouters 方法
2、原來的js進行拆分,拆分成系統菜單和業務菜單,比如404、401、500、登入之類的菜單就不需要放進行資料庫,直接放這本地就行了
iview admin動态路由設計思路開始改造其他唠嗑發現BUG了FK還是有BUG
sysRoutes存是本地菜單
//後端傳回的使用者菜單
export const userRoutes = () => {
  //從本地緩存中拿取菜單
  var jsonRouters = localRead('userRouters');
  //将本地json資料轉成json對象後,再通過backendMenusToRouters方法處理component
  return jsonRouters ? backendMenusToRouters(JSON.parse(jsonRouters)) : []
}

export default [ ...userRoutes(), ...sysRoutes];
           
2、util.js改造
1、添加下面這段代碼拷進去就行了
//#region 動态路由處理
/**
 * @description 将後端菜單樹轉換為路由樹
 * @param {Array} menus
 * @returns {Array}
 */
export const backendMenusToRouters = (menus) => {
  let routers = []  
  forEach(menus, (menu) => {
    // 将後端資料轉換成路由資料
    let route = backendMenuToRoute(menu)
    // 如果後端資料有下級,則遞歸處理下級
    if (menu.children && menu.children.length !== 0) {
      route.children = backendMenusToRouters(menu.children)
    }
    routers.push(route)
  })
  return routers
}

/**
 * @description 将後端菜單轉換為路由
 * @param {Object} menu
 * @returns {Object}
 */
const backendMenuToRoute = (menu) => {
  // 原先routers寫法是component: () => import('@/view/error-page/404.vue')
  let route = Object.assign({}, menu)
  if(route.component)
    route.component = () => import(`@/${menu.component}`)
  return route
}

//#endregion
           

#到這裡需要用到的代碼就貼完了

注意!注意!注意!:這個很重要,一定要看!

原始前端代碼:

component: () => import('@/view/join-page.vue')

component: Main,
           

改造後(資料庫裡隻能存下面這種代碼):

component: 'view/join-page.vue'

component: 'components/main',
           

我遇到的最大困難就是不知道怎麼将後端代碼轉成前端對象,不然我都不用到網上去翻代碼了,哎,怪自己js功底不夠紮實啊~

“component:Main”必須存全路徑“component: ‘components/main’”。或者存成“component: ‘Main’”,注意Main是用單引号引起來的哦!

我參考的這篇文章的代碼是針對Main、parentView做單獨處理,而且必須要引入(import)相應的檔案。我覺得這樣不好,如果要使用其他公共的檔案就得改代碼,是以我直接使用全路徑(components/main)。

外部代碼參考

import Main from '@/components/main' // Main 是架構元件,不在背景傳回,在檔案裡單獨引入
import parentView from '@/components/parent-view' // 擷取元件的方法

// @函數: 周遊背景傳來的路由字元串,轉換為元件對象
export const filterAsyncRouter = asyncRouterMap => {
  const accessedRouters = asyncRouterMap.filter(route => {
    if (route.component) {
      if (route.component === 'Main') {
        // Main元件特殊處理
        route.component = Main
      } else if (route.component === 'parentView') {
        // parentView元件特殊處理
        route.component = parentView
      } else {
        // route.component = _import(route.component)
        route.component = lazyLoadingCop(route.component)
      }
    }
    if (route.children && route.children.length) {
      route.children = filterAsyncRouter(route.children)
    }
    return true
  })
  return accessedRouters
}
           

其他唠嗑

不趕時間的話可以繼續看下》》》

原本我是想把菜單存到user的state中的,但是有幾個問題,

1、重新整理後state資料會丢失

2、state和菜單不是雙向綁定的,由于存進去是異步的,資料還沒開始存菜單就已經加載出來,等資料存進去後菜單也不能自動加載出來。這裡的問題就是:存進去後我不知道應該怎麼通知菜單重新将新增加載新菜單。

3、這裡還有個問題就是菜單是由使用者資訊接口傳回過來的,可以單獨做一個接口來擷取使用者菜單。主要是這個項目不是高并發的業務量也不大,為了節省時間就把他簡化了

發現BUG了

登入後沒有菜單,必須重新整理後才顯示

我做了以下整改
  1. 将菜單存儲改成登入成功後存儲到本地(跟這個BUG沒關系,隻是這樣可以減少接口調用)
  1. 添加下面兩行代碼
    iview admin動态路由設計思路開始改造其他唠嗑發現BUG了FK還是有BUG
  1. app.js修改這3個地方
    iview admin動态路由設計思路開始改造其他唠嗑發現BUG了FK還是有BUG

FK還是有BUG

菜單是正常顯示出來了,但是點了菜單後提示401(無權限)錯誤

不想搞了,來個終極的,登入成功後不用路由跳轉,用href來跳轉,搞定!

iview admin動态路由設計思路開始改造其他唠嗑發現BUG了FK還是有BUG