Vue動態菜單(路由)的實現方案(beforeEach+addRoutes+elementUI)

前端路漫漫,挽起袖子幹前端

前言

我以前總結過動態菜單的實現方案>動態菜單實現,
只不過這篇寫的有點稍微複雜,是用後端返回當前登陸角色的路由表實現的,也就是前端只要從後端取到路由表進行渲染菜單便可;vue

今天,我再講解一種方案:路由表寫在前端,後端返回用戶的角色,前端進行角色對應的菜單渲染ios

在線預覽:動態路由
github(記的star哈):https://github.com/Mrblackant...
圖片描述git

開始以前,本身要大概懂寫關於vue-router的beforeEach(路由攔截)、addRoutes,elementUI的菜單組件等方法,否則理解可能會有點吃力github

思路

分如下幾步:
1.前端在本地寫好路由表,以及每一個路由對應的角色,也就是哪些角色能夠看到這個菜單/路由;
2.登陸的時候,向後端請求獲得登陸用戶的角色(管理者、普通用戶);
3.利用路由攔截,根據取到的用戶角色,跟本地的路由表進行對比,過濾出用戶對應的路由,並利用路由進行左側菜單渲染vue-router

實現

根據上述的3步,咱們進行每一步的實現vuex

1.前端本地寫好路由表
咱們分紅兩個路由表,一個是固定的,好比首頁展現,每一個人都能看到,一個須要根據用戶角色動態展現的;
這裏就利用到了router的meta屬性,咱們在這裏邊寫上菜單對應的:icon,對應的哪些角色能夠看到這個菜單:roles
一個完整的路由表以下:axios

//代碼位置:router/index.js
 {
    path: '',
    component: layout, //總體頁面的佈局(包含左側菜單跟主內容區域)
    children: [{
      path: 'main',
      component: main,
      meta: {
        title: '首頁', //菜單名稱
        roles: ['user', 'admin'], //當前菜單哪些角色能夠看到
        icon: 'el-icon-info' //菜單左側的icon圖標
      }
    }]
  }

2.用戶登陸,取到用戶的角色
原本我是寫了mock數據,模擬用戶登陸,請求後端角色的接口,奈何mock掛了,
因此我就直接模擬了:segmentfault

取到用戶角色,存放進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的路由清除掉,確保下個用戶登錄後,會從新渲染正確的菜單

若是有些地方不理解,師兄建議把不理解的點先單獨拿出來跑跑,
或者看看這篇文章的思路來源:手把手...

若有不正確的地方,還望小夥伴指正哈

相關文章
相關標籤/搜索