很多时候,需要动态加载路由,来控制权限。
基于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() })