一、目的
前端根据后台给的用户角色权限,渲染对应的导航栏
二、实现步骤
- 创建vue实例的时候将vue-router挂载,挂载一些登录的和不需要权限的公用页面
- 用户登录后,获取权限role,将role和路由表每个页面的需要的权限做对比,获取用户最终可访问的路由表
- 在导航守卫获取用户权限,存到vuex里面,每次跳转进行判断,并且调用router.addRoutes(store.getters.addRouters)添加用户可访问的路由。
- 使用vuex管理路由表,根据vuex中可访问的路由渲染侧边栏组件。
三、具体实现
1. 路由添加
PS: 一定要把{path: '*', redirect: '/404', hidden }加在路由最下面,不然后面页面一刷新就找不到路由,会出现404页面
router/index.js
import Vue from 'vue'
import Router from 'vue-router'
Vue.use(Router)
import Layout from '@/layout'
export const constantRoutes = [
// 基础路由
{
path: '/login',
component: () => import('@/views/login/index'),
hidden: true
},
{
path: '/404',
component: () => import('@/views/404'),
hidden: true
},
{
path: '/',
component: Layout,
redirect: '/dashboard',
children: [
{
path: 'dashboard',
name: 'Dashboard',
component: () => import('@/views/dashboard/index'),
meta: { title: '首页', icon: 'dashboard' }
}
]
}
]
export const allMenus = [
// 权限路由
{
path: '/form',
component: Layout,
children: [
{
path: 'index',
name: 'Form',
component: () => import('@/views/empty/index'),
meta: { title: '账号管理', icon: 'form' }
}
]
},
// 404 page must be placed at the end !!!
{ path: '*', redirect: '/404', hidden: true }
]
const createRouter = () =>
new Router({
// mode: 'history', // require service support
scrollBehavior: () => ({ y: 0 }),
routes: constantRoutes
})
const router = createRouter()
export function resetRouter() {
const newRouter = createRouter()
router.matcher = newRouter.matcher // reset router
}
export default router
2、获取用户权限
在导航守卫获取用户权限,存到vuex里面,每次跳转进行判断
permission.js
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'
import { constantRoutes } from '@/router'
NProgress.configure({ showSpinner: false }) // NProgress Configuration
const whiteList = ['/login'] // no redirect whitelist
/* eslint-disable */
router.beforeEach(async (to, from, next) => {
NProgress.start()
document.title = getPageTitle(to.meta.title)
const hasToken = getToken()
if (hasToken) {
if (to.path === '/login') {
next({ path: '/' })
NProgress.done()
} else {
if (!store.getters.limit) {
store
.dispatch('Getpermissions')
.then(resp => {
const menus = constantRoutes
router.options.routes = [...menus, ...store.getters.limit]
router.addRoutes(store.getters.limit)
next({ ...to, replace: true })
})
.catch(err => {
console.log(err)
store.dispatch('FedLogOut').then(() => {
Message.error(error.message || '获取用户权限失败,请重新登录')
next({ path: '/' })
})
})
} else {
next()
}
}
} else {
if (whiteList.indexOf(to.path) !== -1) {
next()
} else {
next(`/login?redirect=${to.path}`)
NProgress.done()
}
}
})
router.afterEach(() => {
NProgress.done()
})
3、权限匹配和存储
store/modules/permission.js
import { getLimit } from '@/api/user'
import { allMenus } from '@/router'
function filterMenus(menus, gnbmArr) {
const finalRouter = menus.filter(menu => {
if (gnbmArr.indexOf(menu.name) >= 0) {
if (menu.children && menu.children.length) {
menu.children = filterMenus(menu.children, gnbmArr)
}
return true
} else {
return false
}
})
return finalRouter
}
const state = {
limit: null,
allMenus: []
}
const mutations = {
SET_LIMIT: (state, limit) => {
console.log(limit)
state.limit = limit
}
}
const actions = {
Getpermissions({ commit }) {
return new Promise((resolve, reject) => {
getLimit().then(resp => {
const gnbmArr = resp.data.map(item => {
return item.gnbm
})
const finalMenus = filterMenus(allMenus, gnbmArr)
commit('SET_LIMIT', finalMenus)
resolve()
})
})
}
}
export default {
state,
mutations,
actions
}
4、侧边栏
使用了vue-element-admin的侧边栏,通过computed获取侧边栏
computed: {
...mapGetters(['sidebar']),
routes() {
return this.$router.options.routes
}
},