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 。
動態路由
具體實現
-
建立vue例項的時候將vue-router掛載,但這個時候vue-router掛載一些登入或者不用許可權的公用的頁面。
-
當用戶登入後,獲取用role,將role和路由表每個頁面的需要的許可權作比較,生成終端使用者可訪問的路由表。
-
呼叫router.addRoutes(store.getters.addRouters)新增使用者可訪問的路由。
-
使用vuex管理路由表,根據vuex中可訪問的路由渲染側邊欄元件。
小建議:這裡還有一個小hack的地方,就是router.addRoutes之後的next()可能會失效,因為可能
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()