關(guān)于vue中根據(jù)用戶權(quán)限動(dòng)態(tài)添加路由的問題
根據(jù)用戶的權(quán)限,展示不同的菜單頁(yè)。
知識(shí)點(diǎn)
路由守衛(wèi)(使用了前置守衛(wèi)):根據(jù)用戶角色判斷要添加的路由
vuex:保存動(dòng)態(tài)添加的路由
難點(diǎn)
每次路由發(fā)生變化時(shí)都需要調(diào)用一次路由守衛(wèi),并且store中的數(shù)據(jù)會(huì)在每次刷新的時(shí)候清空,因此需要判斷store中是否有添加的動(dòng)態(tài)路由。
(若沒有判斷 則會(huì)一直添加 導(dǎo)致內(nèi)存溢出)

根據(jù)角色判斷路由
過濾動(dòng)態(tài)路由 判斷每條路由角色是否與登錄傳入的角色一致

<template>
<div>
<el-menu
:default-active="$route.path"
class="el-menu-vertical-demo menu_wrap"
background-color="#324057"
text-color="white"
active-text-color="#20a0ff"
:collapse="isCollapse"
unique-opened
router
>
<el-submenu
v-for="item in $store.state.Routers"
:key="item.path"
:index="item.path"
v-if="!item.hidden"
>
<template slot="title" >
<i class="el-icon-location"></i>
<span>{{ item.meta.title }}</span>
</template>
<div v-for="chi in item.children" :key="chi.name">
<el-menu-item v-if="!chi.hidden" :index="item.path + '/' + chi.path">
<i class="el-icon-location"></i>{{ chi.meta.title }}
</el-menu-item>
</div>
</el-submenu>
</el-menu>
</div>
</template>
<script>
export default {
name: "MenuList",
data() {
return {
isCollapse: false,
};
},
created() {
this.$bus.$on("getColl", (data) => {
this.isCollapse = data;
});
},
methods: {
}
};
</script>
<style scoped>
.menu_wrap {
height: 100vh;
}
.el-menu-vertical-demo:not(.el-menu--collapse) {
width: 200px;
height: 100vh;
}
</style>
import Vue from 'vue'
import VueRouter from 'vue-router'
import store from '../store/index'
Vue.use(VueRouter)
const originalPush = VueRouter.prototype.push
VueRouter.prototype.push = function push(location) {
return originalPush.call(this, location).catch(err => err)
}
export const routes = [
{
path: '/home',
name: 'First',
component: () => import('../views/Index.vue'),
meta: { title: 'Home'},
children: [
{
path: 'index',
name: 'Home',
component: () => import('../views/Home'),
meta: { title: 'Home', roles: ['Customer'] }
}
]
},
{
path: '/index',
name: 'NavigationOne',
component: () => import('../views/Index.vue'),
meta: { title: '導(dǎo)航一'},
children: [
{
path: 'personnel',
name: 'Personnel ',
component: () => import('../views/One/Personnel.vue'),
meta: { title: 'Personnel', roles: ['Customer'] }
},
{
path: 'account',
name: 'Account',
component: () => import('../views/One/Account.vue'),
meta: { title: 'Account', roles: ['Customer'] }
},
{
path: 'psw',
name: 'psw',
component: () => import('../views/One/Password.vue'),
meta: { title: 'psw', roles: ['Customer'] }
}
]
},
{
path: '/card',
name: 'NavigationTwo',
component: () => import('../views/Index.vue'),
meta: { title: '導(dǎo)航二'},
children: [
{
path: 'activity',
name: 'Activity ',
component: () => import('../views/Three/Activity.vue'),
meta: { title: 'Activity', roles: ['Customer'] }
},
{
path: 'Social',
name: 'Social',
component: () => import('../views/Three/Social.vue'),
meta: { title: 'Social', roles: ['Customer'] }
},
{
path: 'content',
name: 'Content',
component: () => import('../views/Three/Content.vue'),
meta: { title: 'Content', roles: ['Customer'] }
}
]
},
{
path: '/two',
name: 'NavigationThree',
component: () => import('../views/Index.vue'),
meta: { title: '導(dǎo)航三'},
children: [
{
path: 'index',
name: 'Two ',
component: () => import('../views/Two'),
meta: { title: 'Two', roles: ['Customer'] }
}]
},
{
path: '/404',
name: 'Error',
hidden: true,
meta: { title: 'error'},
component: () => import('../views/Error')
}
]
export const asyncRouter = [
// Agent3 Staff2
{
path: '/agent',
component: () => import('../views/Index.vue'),
name: 'Agent',
meta: { title: 'Agent', roles: ['Agent','Staff']},
children: [
{
path: 'one',
name: 'agentOne',
component: () => import('@/views/agent/One'),
meta: { title: 'agentOne', roles: ['Agent','Staff'] }
},
{
path: 'two',
name: 'agentTwo',
component: () => import('@/views/agent/Two'),
meta: { title: 'agentTwo', roles: ['Agent'] }
},
{
path: 'three',
name: 'agentThree',
component: () => import('@/views/agent/Three'),
meta: { title: 'agentThree', roles: ['Agent','Staff'] }
}
]
},
// Staff3
{
path: '/staff',
component: () => import('../views/Index.vue'),
name: 'Staff',
meta: { title: 'Staff', roles: ['Staff']},
children: [
{
path: 'one',
name: 'StaffOne',
component: () => import('@/views/Staff/One'),
meta: { title: 'StaffOne', roles: ['Staff'] }
},
{
path: 'two',
name: 'StaffTwo',
component: () => import('@/views/Staff/Two'),
meta: { title: 'StaffTwo', roles: ['Staff'] }
},
{
path: 'three',
name: 'StaffThree',
component: () => import('@/views/Staff/Three'),
meta: { title: 'StaffThree', roles: ['Staff'] }
}
]
},
{ path: '*', redirect: '/404', hidden: true }
]
const router = new VueRouter({
routes
})
router.beforeEach((to, from, next) =>{
let roles = ['Staff']
if(store.state.Routers.length) {
console.log('yes')
next()
} else {
console.log('not')
store.dispatch('asyncGetRouter', {roles})
.then(res =>{
router.addRoutes(store.state.addRouters)
})
next({...to})
// next()與next({ ...to })的區(qū)別:next() 放行 next('/XXX') 無(wú)限攔截
}
})
export default router
import Vue from 'vue'
import Vuex from 'vuex'
import modules from './module'
import router, {routes, asyncRouter} from '../router'
function hasPermission(route, roles) {
if(route.meta && route.meta.roles) {
return roles.some(role =>route.meta.roles.indexOf(role) >= 0)
} else {
return true
}
}
/*
遞歸過濾異步路由表 返回符合用戶角色的路由
@param asyncRouter 異步路由
@param roles 用戶角色
*/
function filterAsyncRouter(asyncRouter, roles) {
let filterRouter = asyncRouter.filter(route =>{
if(hasPermission(route, roles)) {
if(route.children && route.children.length) {
route.children = filterAsyncRouter(route.children, roles)
}
return true
}
return false
})
return filterRouter
}
Vue.use(Vuex)
export default new Vuex.Store({
state: {
addRouters: [],
Routers: []
},
mutations: {
getRouter(state, paload) {
// console.log(paload)
state.Routers = routes.concat(paload)
state.addRouters = paload
// router.addRoutes(paload)
}
},
actions: {
asyncGetRouter({ commit }, data) {
const { roles } = data
return new Promise(resolve =>{
let addAsyncRouters = filterAsyncRouter(asyncRouter, roles)
commit('getRouter', addAsyncRouters)
resolve()
})
}
}
})
到此這篇關(guān)于vue中根據(jù)用戶權(quán)限動(dòng)態(tài)添加路由詳解的文章就介紹到這了,更多相關(guān)vue動(dòng)態(tài)添加路由內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Vue中select下拉框的默認(rèn)選中項(xiàng)的三種情況解讀
這篇文章主要介紹了Vue中select下拉框的默認(rèn)選中項(xiàng)的三種情況解讀,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-05-05
Vue2 配置 Axios api 接口調(diào)用文件的方法
本篇文章主要介紹了Vue2 配置 Axios api 接口調(diào)用文件的方法,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來(lái)看看吧2017-11-11
vue 使用v-for進(jìn)行循環(huán)的實(shí)例代碼詳解
這篇文章主要介紹了vue 使用v-for進(jìn)行循環(huán)的實(shí)例代碼詳解,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-02-02
vue 組件數(shù)據(jù)加載解析順序的詳細(xì)代碼
Vue.js的解析順序可以概括為:模板編譯、組件創(chuàng)建、數(shù)據(jù)渲染、事件處理和生命周期鉤子函數(shù)執(zhí)行,接下來(lái)通過本文給大家介紹vue 組件數(shù)據(jù)加載解析順序的完整代碼,感興趣的朋友跟隨小編一起看看吧2024-03-03
Vue+Element實(shí)現(xiàn)封裝抽屜彈框
這篇文章主要為大家詳細(xì)介紹了如何利用Vue和Element實(shí)現(xiàn)簡(jiǎn)單的抽屜彈框效果,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2023-06-06
Vue檢測(cè)屏幕變化來(lái)改變不同的charts樣式實(shí)例
這篇文章主要介紹了Vue檢測(cè)屏幕變化來(lái)改變不同的charts樣式實(shí)例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來(lái)看看吧2020-10-10
vuecli項(xiàng)目構(gòu)建SSR服務(wù)端渲染的實(shí)現(xiàn)
這篇文章主要介紹了vuecli項(xiàng)目構(gòu)建SSR服務(wù)端渲染的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-10-10
vue監(jiān)聽滾動(dòng)事件實(shí)現(xiàn)滾動(dòng)監(jiān)聽
本文主要介紹了vue監(jiān)聽滾動(dòng)事件實(shí)現(xiàn)滾動(dòng)監(jiān)聽的相關(guān)資料。具有很好的參考價(jià)值。下面跟著小編一起來(lái)看下吧2017-04-04
Vue?props傳入function時(shí)的this指向問題解讀
這篇文章主要介紹了Vue?props傳入function時(shí)的this指向問題解讀,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-01-01

