很多時候,需要動態加載路由,來控制權限。
基於element ui 得動態路由寫法
1.設置不需要權限的路由constantRoutes和需要判斷權限的路由asyncRoutes ,動態過濾需要判斷權限的路由,並通過addRoutes添加路由
router/index,js
/*
* @Descripttion:
* @Version:
* @Date: 2021-06-11 13:58:03
*/
import Vue from 'vue'
import Router from 'vue-router'
Vue.use(Router)
/* Layout */
import Layout from '@/layout'
/**
* constantRoutes
* a base page that does not have permission requirements
* all roles can be accessed
*/
// 這里放着不需要判斷權限的路由
export const constantRoutes = [{
path: '/login',
component: () => import('@/views/login/index'),
hidden: true
},
// 作品評審
{
path: '/theme',
redirect: '/theme/list',
name: 'theme',
component: Layout,
meta: {
title: '作品評審',
icon: 'dashboard',
},
children: [{
meta: {
title: '作品評審',
icon: 'dashboard',
},
name: 'themelist',
path: 'list',
component: () => import('@/views/theme/list'),
},
{
meta: {
title: '作品評審',
icon: 'dashboard',
activeMenu: '/theme/list'
},
name: 'themeadd',
hidden: true,
path: 'add',
component: () => import('@/views/theme/add'),
},
]
},
]
// 需要判斷權限的路由
export const asyncRoutes = [{
path: '/',
redirect: '/list',
name: 'dat',
component: Layout,
meta: {
title: '數據管理',
icon: 'example',
// 區分權限得標識
roles: ["管理員"]
},
children: [{
meta: {
title: '數據管理',
icon: 'example'
},
path: 'list',
name: 'manageList',
component: () => import('@/views/area/list.vue'),
},
{
meta: {
title: '數據管理',
icon: 'example',
activeMenu: '/list'
},
path: 'add',
name: 'manageAdd',
component: () => import('@/views/area/add.vue'),
hidden: true
},
]
},
// 賬號管理
{
path: '/tag',
redirect: '/tag/list',
name: 'tag',
component: Layout,
meta: {
title: '賬號管理',
icon: 'example',
// 區分權限得標識
roles: ["管理員"]
},
children: [{
meta: {
title: '賬號管理',
icon: 'example'
},
path: 'list',
name: 'taglist',
component: () => import('@/views/tag/list.vue'),
},
{
meta: {
title: '賬號管理',
icon: 'example',
activeMenu: '/tag/list'
},
path: 'add',
name: 'tagadd',
component: () => import('@/views/tag/add.vue'),
hidden: true
},
]
},
{
path: '*',
redirect: '/404',
hidden: true
}
]
const createRouter = () => new Router({
// mode: 'history', // require service support
scrollBehavior: () => ({
y: 0
}),
routes: constantRoutes
})
const router = createRouter()
// Detail see: https://github.com/vuejs/vue-router/issues/1234#issuecomment-357941465
export function resetRouter() {
const newRouter = createRouter()
router.matcher = newRouter.matcher // reset router
}
router.beforeEach((to, from, next) => {
if (to.path === '/login') {
next();
} else {
let token = localStorage.getItem('Authorization');
if (token === 'null' || token === '') {
next('/login');
} else {
next();
}
}
});
export default router
登錄login.vue
this.$store.dispatch("user/login", this.loginForm)
store中user模塊 store/modules/user.js
import {
login,
logout,
getInfo
} from '@/api/user'
import {
getToken,
setToken,
removeToken
} from '@/utils/auth'
import router, {
resetRouter
} from '@/router'
const state = {
token: getToken(),
name: '',
avatar: '',
introduction: '',
roles: ""
}
const mutations = {
SET_TOKEN: (state, token) => {
state.token = token
},
SET_INTRODUCTION: (state, introduction) => {
state.introduction = introduction
},
SET_NAME: (state, name) => {
state.name = name
},
SET_AVATAR: (state, avatar) => {
state.avatar = avatar
},
SET_ROLES: (state, roles) => {
state.roles = roles
}
}
const actions = {
// 登錄
login({
commit
}, userInfo) {
const {
username,
password
} = userInfo
return new Promise((resolve, reject) => {
// 數據結構
// var res={
// token:"123",
// username:"123",
// role:"管理員"
// }
// 調用登錄方法 走接口
login({
username: username.trim(),
password: password
}).then(response => {
console.log(response)
var res = response.data;
// 登錄成功后將token存儲在cookie之中
setToken(res.token)
sessionStorage.setItem('username', res.username)
sessionStorage.setItem('role', res.role)
sessionStorage.setItem('id', res.id)
commit('SET_NAME', res.username)
commit('SET_TOKEN', res.token)
// commit('SET_ROLES', res.role)
// commit('SET_ROLES', response.data.role)
resolve()
}).catch(error => {
reject(error)
})
})
},
// 設置角色
setRole({
commit
}, role) {
commit('SET_ROLES', role)
},
// 等處登錄
logout({
commit,
state,
dispatch
}) {
return new Promise((resolve, reject) => {
logout(state.token).then(() => {
commit('SET_TOKEN', '')
commit('SET_ROLES', "")
removeToken()
resetRouter()
// reset visited views and cached views
// to fixed https://github.com/PanJiaChen/vue-element-admin/issues/2485
dispatch('tagsView/delAllViews', null, {
root: true
})
resolve()
}).catch(error => {
reject(error)
})
})
},
// 移除token
resetToken({
commit
}) {
return new Promise(resolve => {
commit('SET_TOKEN', '')
commit('SET_ROLES', "")
removeToken()
resolve()
})
},
}
export default {
namespaced: true,
state,
mutations,
actions
}
store/modules/permission.js 過濾動態路由,
/* * @Descripttion: * @Version: 1.0.1 * @Date: 2021-06-11 13:58:03 */ import { constantRoutes, asyncRoutes } from '@/router' /** * 使用meta.role確定當前用戶是否具有權限 * @param roles * @param route */ function hasPermission(roles, route) { if (route.meta && route.meta.roles) { return roles.some(role => route.meta.roles.includes(role)) } else { return true } } /** * 遞歸過濾異步路由表 * @param routes asyncRoutes * @param roles */ export function filterAsyncRoutes(routes, roles) { console.log(routes, roles) const res = [] routes.forEach(route => { const tmp = { ...route } if (hasPermission(roles, tmp)) { if (tmp.children) { tmp.children = filterAsyncRoutes(tmp.children, roles) } res.push(tmp) } }) return res } const state = { routes: [], addRoutes: [] } const mutations = { SET_ROUTES: (state, routes) => { state.addRoutes = routes; state.routes = constantRoutes.concat(routes); console.log(state.routes) } } const actions = { generateRoutes({ commit }, roles) { return new Promise(resolve => { let accessedRoutes; // 管理員是最高權限,所有路由均可訪問得情況下 就把注釋放出來 // if (roles.includes('管理員')) { // accessedRoutes = asyncRoutes || [] // } else { // 獲取符合條件的需要添加的動態路由 accessedRoutes = filterAsyncRoutes(asyncRoutes, roles) // } commit('SET_ROUTES', accessedRoutes) resolve(accessedRoutes) }) } } export default { namespaced: true, state, mutations, actions }
全局路由守衛 permission.js
/* * @Descripttion: * @Version: 1.0.1 * @Date: 2021-06-11 13:58:03 */ import router from './router' import store from './store' import { Message } from 'element-ui' import NProgress from 'nprogress' // progress bar import 'nprogress/nprogress.css' // progress bar style import { getToken } from '@/utils/auth' // get token from cookie import getPageTitle from '@/utils/get-page-title' NProgress.configure({ showSpinner: false }) // NProgress Configuration router.beforeEach(async (to, from, next) => { // start progress bar NProgress.start() // set page title document.title = getPageTitle(to.meta.title) // determine whether the user has logged in const hasToken = getToken() if (hasToken) { if (to.path === '/login') { // if is logged in, redirect to the home page next({ path: '/' }) NProgress.done() // hack: https://github.com/PanJiaChen/vue-element-admin/pull/2939 } else { // determine whether the user has obtained his permission roles through getInfo const hasRoles = store.getters.roles if (hasRoles) { next() } else { try { // 登陸以后獲取到用戶角色,用來判斷權限 const roles = sessionStorage.getItem('role') // 寫入角色 store.dispatch('user/setRole', roles) // 獲取需要動態添加得路由 const accessRoutes = await store.dispatch('permission/generateRoutes', [roles]) router.options.routes = store.getters.routes; // 動態添加可訪問路由 router.addRoutes(accessRoutes) //hack方法以確保addRoutes是完整的 //設置replace:true,這樣導航就不會留下歷史記錄 next({ ...to, replace: true }) } catch (error) { // 刪除token並轉到登錄頁以重新登錄 await store.dispatch('user/resetToken') Message.error(error || 'Has Error') next(`/login?redirect=${to.path}`) NProgress.done() } } } } else { // 這里可以設置白名單 ,不需要判斷得路由導航,例如注冊,登錄等,可以用數組,可以直接比較 if (to.path.includes('login')) { next() } else { // 沒有訪問權限的其他頁將重定向到登錄頁 next(`/login?redirect=${to.path}`) NProgress.done() } } }) router.afterEach(() => { // finish progress bar NProgress.done() })
