感謝這篇文章:https://blog.csdn.net/weixin_34179968/article/details/92579951
網上找到了好多文章就這篇靠譜點,隻少能靠這篇文章把功能做出來。唯一缺點就是提供的代碼沒有後端,程式跑不起來。不過還好,有代碼參考也不錯。
這裡我不得不吐槽一下網上有的文章,太TMD坑,甚至還有故意留坑讓你自己去排查的,心中簡直就是萬馬奔騰的趕腳~
設計思路
- 通過改造擷取使用者資訊接口,有使用者資訊接口提供使用者資訊和菜單權限,并将菜單權限存到本地(user.js檔案改造)
- 改造本地路由(router.js檔案改造)
-
添加菜單解析方法(util.js添加方法)
就這麼簡單,隻需要這三步就行了,不知道網上的怎本寫的那麼複雜。
開始改造
- 1、将擷取到的菜單存到本地緩存(user.js改造),使用者登入成功後将菜單存到本地
- 引入localSave方法
- 将資料存到本緩存(這個資料是由後端傳回的,你可以先直接寫個死資料在這) 如果你還沒開始對接後端的話,那就直接考下面代碼替換黃色的部分即可
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、登入之類的菜單就不需要放進行資料庫,直接放這本地就行了
- 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了
登入後沒有菜單,必須重新整理後才顯示
- 我做了以下整改
-
- 将菜單存儲改成登入成功後存儲到本地(跟這個BUG沒關系,隻是這樣可以減少接口調用)
-
- 添加下面兩行代碼
-
- app.js修改這3個地方
FK還是有BUG
菜單是正常顯示出來了,但是點了菜單後提示401(無權限)錯誤
不想搞了,來個終極的,登入成功後不用路由跳轉,用href來跳轉,搞定!