1. 程式人生 > >vue 配置路由 + 使用者許可權生成動態路由 踩過的那些坑

vue 配置路由 + 使用者許可權生成動態路由 踩過的那些坑

整個動態路由的設定是我自己研究寫的,現在專案中沒發現什麼問題。如發現有問題,歡迎前來糾正,謝謝!!!

連結:https://pan.baidu.com/s/1x3s6jhScv5b0K-3knRFcTg 密碼:d7fv
此包因為涉及後臺互動,下載後不可本地執行。可以參考專案中相關頁面的設定

cnpm install vue-router --save

注意引數--save

  --save 可以理解成生產環境,會把依賴包名稱新增到 package.json 檔案 dependencies 鍵下,dependencies是執行時依賴。

  --save-dev 則是開發環境, 新增到 package.json 檔案 devDependencies 鍵下,devDependencies是開發時的依賴,如生產時不需要用到壓縮庫應該安裝到devDependencies 。

動態路由

具體實現

  1. 建立vue例項的時候將vue-router掛載,但這個時候vue-router掛載一些登入或者不用許可權的公用的頁面。

  2. 當用戶登入後,獲取用role,將role和路由表每個頁面的需要的許可權作比較,生成終端使用者可訪問的路由表。

  3. 呼叫router.addRoutes(store.getters.addRouters)新增使用者可訪問的路由。

  4. 使用vuex管理路由表,根據vuex中可訪問的路由渲染側邊欄元件。

小建議:這裡還有一個小hack的地方,就是router.addRoutes之後的next()可能會失效,因為可能

next()的時候路由並沒有完全add完成,好在查閱文件發現

next('/') or next({ path: '/' }): redirect to a different location. The current navigation will be aborted and a new one will be started.

根據許可權生成動態路由步驟:

1.路由配置

main.js

  

router: router.js  index.js

 

2.登入成功  因路由還是預設路由,頁面跳轉到404,解決方法如下:

login.js  動態新增路由

3.頁面重新整理  頁面跳轉到404,解決方法如下:

這是因為重新整理會導致Vue重新例項化,路由也恢復到了初始路由,於是當前路徑又被重定向到了404,

這個問題的根源是可用路由沒有實現持久化,

那麼可以通過將路由資料存sessionStorage來解決,例項化之前如果檢測到本地路由就直接合並路由

解決辦法:初始路由刪除404配置,動態新增

router.js

main.js

4.選單欄始終未空  未能載入路由

1.addroute已經成功了,所以可以跳轉到新增的路由頁。

2. addroute只是在路由里加了新的路由,也就是你可以通過url跳轉,並不是個你新增新的選單,加新的選單還需要你自己根據許可權判斷,寫程式碼處理

3.渲染menu不應該遍歷路由去生成,因為addroutes後,路由雖然增加了,但路由不是響應資料(未觀察,且未訂閱),是不會對你的檢視觸發變化的。

解決辦法:指令    Vue.directive

建議解決方案:使用vuex,對路由資訊進行狀態管理,把初始的路由資料存到store裡,menu依靠store進行渲染及更新,addroutes後再把新增路由push進store儲存的路由陣列中,即可以觸發menu更新。

----------------------------------------------------------------------------------------------------------------------

實際步驟:

①store module : permission.js

 action:GenerateRoutes   根據角色生成動態路由

import { constRouters, appRouterAdmain, appRouterManger, appRouterYyb } from '../../routes/routes'
/**

* 通過meta.role判斷是否與當前使用者許可權匹配

* @param roles

* @param route

*/

function hasPermission(roles, route) {

  if (route.meta && route.meta.roles) {

    return roles.some(role => route.meta.roles.indexOf(role) >= 0)

  } else {

    return true

  }

}
/**

* 遞迴過濾非同步路由表,返回符合使用者角色許可權的路由表

* @param asyncRouterMap

* @param roles

*/
function filterAsyncRouter(asyncRouterMap, roles) {

      const accessedRouters = asyncRouterMap.filter(route => {

        if (hasPermission(roles, route)) {

             if (route.children && route.children.length) {

                route.children = filterAsyncRouter(route.children, roles)

              }

          return true

        }

        return false

      })

      return accessedRouters

}
const permission = {

      state: {

        routers: constRouters,

        addRouters: []

      },

      mutations: {

        SET_ROUTERS: (state, routers) => {

              state.addRouters = routers

              state.routers = constRouters.concat(routers)

        }

      },

      actions: {

        GenerateRoutes({ commit }, data) {

              return new Promise(resolve => {

                const { roles } = data

                let accessedRouters

                console.log(data)

                if (roles.indexOf('admin') >= 0) {

                      accessedRouters = appRouterAdmain

                }else if (roles.indexOf('shenhe') >= 0) {

                      accessedRouters = appRouterManger

                }else if (roles.indexOf('999') >= 0) {

                      accessedRouters = appRouterYyb

                }

                commit('SET_ROUTERS', accessedRouters);

                resolve()

              })

        }

      }

}
export default permission

 ②getter 方法

③home.vue  匯入store 資料

5.router.beforEach 無限迴圈,頁面跳轉不會觸發無限迴圈,重新整理頁面就會

原因:

呼叫next()時會直接進入to路由,不會再呼叫beforeEach()

而呼叫next('xxx')後會攔截路由使得路由重定向xxx,並再次呼叫beforeEach(),因此必須做好條件判斷避免陷入死迴圈。

解決步驟:

①將所有next('xxx') --> next()  問題還是沒解決。

②發現是重複新增路由造成。

Home.vue 已經呼叫了路由新增功能,與 router.beforeEach 新增路由重複衝突

5.靜態路由正常。動態路由重新整理頁面不能展開當前路由  點選跳轉沒問題

    猜想:

    ①可能是因為路由是動態載入,動態路由在for迴圈之後,所以未能展開

    ②可能是vue 引數傳的不對

        

解決辦法:

① 固定展示某一項  :default-openeds="['1']"

   

    問題: 但是每次點選切換其他路由,路由重新整理 固定指向第一個路由。

②需動態展示當前欄目

第一次進入頁面/重新整理頁面           點選切換頁面正常顯示

          

相關動態路由設定程式碼:

  

6.換一種路由新增方式

home.vue 去掉動態更改路由方法

menuItem: function() {

      // 動態獲取可訪問路由表

      // this.$router.options.routes = this.$store.state.permission.addRouters;

      // return this.$store.state.permission.addRouters

}  

效果:

首次登入:                                           重新整理頁面:

    

路由由vuex獲取:

import store from "../vuex/store"

main.js 設定路由

new Vue({

    router,

       store,

       render: h => h(App),

       created: function() {

              let isLogin = util.getCookie('role');

              if(!isLogin){

                     return this.$router.push({path:'/login'});

              }

              

              //存選單

              let userPath = '';

              if(isLogin == 20){

                     userPath = constRouters.concat(appRouterManger);

              }else if(isLogin == 50){

                      userPath = constRouters.concat(appRouterYyb);

              }else{

                      userPath = constRouters.concat(appRouterAdmain);

              }      

              //注入時拼接404處理路由

              this.$router.addRoutes(userPath.concat([{

                      path: '*',

                      redirect: '/404'

              }]));

              // 因為addroutes後,$router.options.routes不會更新,所以需要手動新增。

                          //  最後發現這句話可以不加

              this.$router.options.routes = userPath;

       },

       mounted () {

   }

}).$mount('#app')

main.js  --> router.beforeEach   使用者許可權路由有store分配

new Vue({
    .....
    //存選單    
    let userPath = '';
    if(isLogin == 20){
         userPath = constRouters.concat(appRouterManger);
    }else if(isLogin == 50){
         userPath = constRouters.concat(appRouterYyb);
    }else{
         userPath = constRouters.concat(appRouterAdmain);
    }      
    //注入時拼接404處理路由
    this.$router.addRoutes(userPath.concat([{
         path: '*',
         redirect: '/404'
    }]));
})

上面的存選單程式碼塊替換為:

let userPath = constRouters.concat(store.getters.addRouters);
//注入時拼接404處理路由
this.$router.addRoutes(userPath.concat([{
     path: '*',
     redirect: '/404'
}]));

vuex - moudle - permission.js  設定許可權路由:

登陸成功後頁面為空:

解決辦法:

login.vue  登入介面內部手動新增路由 :   this.$router.addRouters()