很多時候,需要動態加載路由,來控制權限。
基於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() })