前言
我之前總結過動態菜單的實現方案>動態菜單實現,
只不過這篇寫的有點稍微復雜,是用后端返回當前登錄角色的路由表實現的,也就是前端只要從后端取到路由表進行渲染菜單即可;
今天,我再講解一種方案:路由表寫在前端,后端返回用戶的角色,前端進行角色對應的菜單渲染
在線預覽:動態路由
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的路由清除掉,確保下個用戶登陸后,會重新渲染正確的菜單
如果有些地方不理解,師兄建議把不理解的點先單獨拿出來跑跑,
或者看看這篇文章的思路來源:手把手...
如有不正確的地方,還望小伙伴指正哈