前言
我之前總結過動态菜單的實作方案>動态菜單實作,
隻不過這篇寫的有點稍微複雜,是用後端傳回目前登入角色的路由表實作的,也就是前端隻要從後端取到路由表進行渲染菜單即可;
今天,我再講解一種方案:路由表寫在前端,後端傳回使用者的角色,前端進行角色對應的菜單渲染
線上預覽:動态路由github(記的star哈):https://github.com/Mrblackant...
開始之前,自己要大概懂寫關于vue-router的beforeEach(路由攔截)、addRoutes,elementUI的菜單元件等方法,不然了解可能會有點吃力
思路
分以下幾步:
1.前端在本地寫好路由表,以及每個路由對應的角色,也就是哪些角色可以看到這個菜單/路由;
2.登入的時候,向後端請求得到登入使用者的角色(管理者、普通使用者);
3.利用路由攔截,根據取到的使用者角色,跟本地的路由表進行對比,過濾出使用者對應的路由,并利用路由進行左側菜單渲染
實作
根據上述的3步,我們進行每一步的實作
1.前端本地寫好路由表
我們分成兩個路由表,一個是固定的,比如首頁展示,每個人都能看到,一個需要根據使用者角色動态展示的;
這裡就利用到了router的meta屬性,我們在這裡邊寫上菜單對應的:icon,對應的哪些角色可以看到這個菜單:roles
一個完整的路由表如下:
//代碼位置:router/index.js
{
path: '',
component: layout, //整體頁面的布局(包含左側菜單跟主内容區域)
children: [{
path: 'main',
component: main,
meta: {
title: '首頁', //菜單名稱
roles: ['user', 'admin'], //目前菜單哪些角色可以看到
icon: 'el-icon-info' //菜單左側的icon圖示
}
}]
}
2.使用者登入,取到使用者的角色
本來我是寫了mock資料,模拟使用者登入,請求後端角色的接口,奈何mock挂了,
是以我就直接模拟了:
取到使用者角色,存放進localStorage,然後跳轉首頁
//代碼位置:src/components/reLoad.vue
// axios.post('/temp',this.formModel).then(res=>{})
// 我暫時就不模拟了,直接取
let getUserRole = this.formModel.user === 'admin' ? 'admin' : 'user'
localStorage.setItem('userRole', getUserRole)
this.$router.push({
path: '/main'
})
3.路由攔截beforeEach,并過濾出角色對應的路由表
經過第2步,我們已經得到了使用者的角色,這時候在路由攔截的地方我們就可以取到了,
取到之後,結合第1步我們寫好的路由,利用數組的filter方法,拿角色跟路由表裡meta标簽裡的roless資料進行對比
過濾好了,拿目前路由去渲染左側菜單,這一步其實可以用vuex去實作,我擔心有的小夥伴不了解,就用一個global(全局變量)替代了
尤其要注意路由攔截這裡,很容易陷入死循環,是以我建議大家先了解一下beforeEach和addRoutes的運作機制
//代碼位置:src/permission.js
router.beforeEach((to, from, next) => {
// 取到使用者的角色
let GetRole = localStorage.getItem("userRole")
// 如果登入了
if (GetRole !== 'unload') {
next() //next()方法後的代碼也會執行
// 1.如果路由表 沒根據角色進行篩選,就篩選一次
if (!addRouFlag) {
addRouFlag = true
// 2.根據使用者的角色、和需要動态展示的路由,生成符合使用者角色的路由
var getRoutes = baseRoleGetRouters(permissionRouter, GetRole.split(","))
// 3.利用global屬性,讓渲染菜單的元件sideMeuns.vue重新生成左側菜單
global.antRouter = fixedRouter.concat(getRoutes)
// 4.将生成好的路由addRoutes
router.addRoutes(fixedRouter.concat(getRoutes))
// 5.push之後,會重新進入到beforeEach的鈎子裡,直接進入第一個if判斷
router.push({ path: to.path })
}
} else {
// 使用者沒登入,跳轉到登入頁面
if (to.path === '/') {
next()
} else {
next('/')
}
}
})
整體流程走完了,再容易讓人蒙的地方
1.根據路由進行菜單展示
代碼位置:/src/components/sideMeuns.vue,
先看下elementUI菜單元件,把一些基礎的參數先了解一下,
這裡我把菜單渲染寫成了一個元件:
用到了遞歸屬性,保證可以生成多級菜單,
我建議不熟悉的,大家用元件先模拟着寫一個包含跳轉功能、icon展示的菜單,然後再看我寫的元件
2.使用者退出系統
代碼位置:/src/components/layout.vue
退出的時候,記得清除掉存在localStorage的使用者角色,
然後利用 window.location.href = "/"跳轉到登入頁,
為什麼要用location.href,這樣會把之前addRoutes的路由清除掉,確定下個使用者登陸後,會重新渲染正确的菜單