动态路由设置一般有两种:
(1)、简单的角色路由设置:比如只涉及到管理员和普通用户的权限。通常直接在前端进行简单的角色权限设置
(2)、复杂的路由权限设置:比如OA系统、多种角色的权限配置。通常需要后端返回路由列表,前端渲染使用
1、简单的角色路由设置
(1)配置项目路由权限
// router.js
import Vue from 'vue'
import Router from 'vue-router'
import Layout from '@/layout'
Vue.use(Router)
// 权限路由列表
let asyncRoutes = [
{
path: '/',
component: Layout,
redirect: () => import('@/views/index'),
redirect: '/home',
meta: {
roles:[1,2,3] //三种角色
},
children: [
{
path: 'home',
component: () => import('@/views/home'),
meta: {
title: 'tIndex',
roles:[1,2,3]
}
},
{
path: 'member',
component: () => import('@/components/animate'),
meta: {
title:'tMember',
roles:[1,2]
},
children:[
{
path:'',
component: () => import('@/views/member'),
name:'member',
meta:{
roles:[1,2]
},
},
{
path:'detail',
component: () => import('@/views/member/detail'),
name:'memberDetail',
meta:{
title:'tMemberDetail',
roles:[1,2]
}
},
{
path:':scoreId/score',
component: () => import('@/views/member/score'),
name:'score',
meta:{
title:'tScore',
roles:[1,2]
}
}
]
},
]
},
]
// 静态路由
let defaultRouter = [{
path: '/404',
name: '404',
component: () => import('@/views/404/index'),
meta: {
title: '404'
}
},{
path: '/login',
name: 'login',
component: () => import('@/views/login'),
meta: {
title:'tLogin'
},
}]
export const router = new VueRouter({
mode: 'history',
base: process.env.BASE_URL,
routes: defaultRouter
})
2)新建一个公共的asyncRouter.js文件
function hasPermission(roles, route) {
if (route.meta && route.meta.roles) {
return roles.some(role => route.meta.roles.includes(role))
} else {
return false
}
}
// 递归过滤异步路由表,筛选角色权限路由
export function filterAsyncRoutes(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
}
(3)创建路由守卫 在main.js当中
// import NProgress from 'nprogress' // 进度条插件
// import 'nprogress/nprogress.css' // 进度条样式
import store from './store'
import storage from '@/utils/storage.js'
import { router, routes } from './router'
import { filterAsyncRoutes } from './router/asyncRouter.js'
const whiteList = ['/login']
router.beforeEach(async(to, from, next) => {
(to.matched[to.matched.length - 1]?.path === to.matched[to.matched.length - 2]?.path + '/') && to.query ? to.matched[to.matched.length - 2].meta.query = to.query : 0
// 进度条开始
// NProgress.start()
// 获取路由 meta 中的title,并设置给页面标题
// document.title = to.meta.title
// 获取用户登录的token
const hasToken = storage.getLocal('userinfo') && storage.getLocal('userinfo').token
// 判断当前用户是否登录
if (hasToken) {
if (to.path === '/login') {
next({ path: '/' })
// NProgress.done()
} else {
// 从store中获取用户角色
const hasRoles = store.state.routes && store.state.routes.length > 0
if (hasRoles) {
next()
} else {
try {
// 获取用户角色
const roles = await store.state.adminUser.auth
// 通过用户角色,获取到角色路由表
const accessRoutes = filterAsyncRoutes(routes,[roles])
// 动态添加路由到router内
router.matcher.addRoutes(accessRoutes)
store.commit('saveRoute',accessRoutes)
next({ ...to, replace: true })
} catch (error) {
// 清除用户登录信息后,回跳到登录页去
storage.removeLocal('userinfo')
storage.removeLocal('token')
store.state.routes = null
next(`/login?redirect=${to.path}`)
// NProgress.done()
}
}
}
} else {
// 用户未登录
if (whiteList.indexOf(to.path) !== -1) {
// 需要跳转的路由是否是whiteList中的路由,若是,则直接条状
next()
} else {
// 需要跳转的路由不是whiteList中的路由,直接跳转到登录页
next(`/login?redirect=${to.path}`)
// 结束精度条
// NProgress.done()
}
}
})
// router.afterEach(() => {
// // 结束精度条
// NProgress.done()
// })
(4)在login登录的时候将roles存储到store中
import storage from '@/utils/storage.js'
const mutations = {
saveUserInfo (state, data) {
storage.setLocal('token',data.token)
storage.setLocal('userinfo', data)
state.adminUser = data
},
saveRoute (state, data) {
state.routes = data
},
}
export default mutations
login.vue
import { mapMutations } from "vuex";
export default {
name: "login",
data() {
return {
ruleForm: {
username: "",
password: "",
},
rules: {
username: [
{
required: true,
message: '输入帐号',
trigger: "blur",
},
{ min: 3, message: this.$t('min3'), trigger: "blur" },
],
password: [
{
required: true,
message: '输入密码',
trigger: "blur",
},
{ min: 6, message: this.$t('min6'), trigger: "blur" },
],
},
};
},
methods: {
...mapMutations(["saveUserInfo"]),
async submitAdmin(formName) {
await this.$refs[formName].validate();
this.loginHandle(this.ruleForm);
},
async loginHandle(ruleForm) {
let res = await login(ruleForm);
if (res.code) return;
this.saveUserInfo(res);
this.$router.push("/");
this.$message.success({
message: this.$t('loginSuccess'),
});
},
},
};
2、复杂的路由权限设置(后端动态返回路由数据)
https://www.jianshu.com/p/4f2566b67989