参考文献:http://www.devopser.org/articles/2019/04/29/1556524856420.html
从后端获取路由表,根据路由表展示权限菜单栏
前端真实的路由表长这样
import Vue from 'vue'
import Router from 'vue-router'
import store from '@/store'
import {getUserRouters} from "../api/user"
Vue.use(Router)
import Layout from '@/layout'
export const constantRoutes = [
//平台管理
{
path: '/platformManage',
component: Layout,
redirect: '/platformManage',
name: 'platformManage',
meta: {
title: '平台管理',
icon: '平台管理'
},
children: [
{
path: '/objectManage',
// name: "objectManage",
component: () => import('@/views/platformManage/objectManage'),
meta: {
title: '对象管理',
icon: '对象管理'
},
redirect:'/objectManage/organManage',
children: [
{
// path: '/objectManage/organManage',
path: 'organManage',
component: () => import('@/views/platformManage/objectManage/organManage'),
hidden: true,
isShow: true,
meta: { title: '机构管理' }
},
{
// path: '/objectManage/branchManage',
path: 'branchManage',
component: () => import('@/views/platformManage/objectManage/branchManage'),
hidden: true,
isShow: true,
meta: { title: '部门管理' }
},
{
// path: '/objectManage/userManage',
path: 'userManage',
component: () => import('@/views/platformManage/objectManage/userManage'),
hidden: true,
isShow: true,
meta: { title: '用户管理' }
},
{
// path: '/objectManage/userManage',
path: 'menuManage',
component: () => import('@/views/platformManage/objectManage/menuManage'),
hidden: true,
isShow: true,
meta: { title: '菜单管理' }
},
{
// path: '/objectManage/userManage',
path: 'submitManage',
component: () => import('@/views/platformManage/objectManage/submitManage'),
hidden: true,
isShow: true,
meta: { title: '报送菜单管理' }
}
]
},
{
path: '/powerManage',
component: () => import('@/views/platformManage/powerManage'),
meta: { title: '权限管理', icon: "权限管理" },
redirect:'/powerManage/resourceAllocation',
children: [
{
path: 'resourceAllocation',
component: () => import('@/views/platformManage/powerManage/resourceAllocation'),
hidden: true,
isShow: true,
meta: { title: '资源分配' }
},
{
path: 'dataAllocation',
component: () => import('@/views/platformManage/powerManage/dataAllocation'),
hidden: true,
isShow: true,
meta: { title: '数据分配' }
}
]
}
]
},
]
后端的路由表长这样
export const constantRoutes = [
{
"path": "/platformManage",
"component": "Layout",
"hidden": 0,
"isShow": "0",
"meta": {
"title": "平台管理",
"icon": "dashboard"
},
"children": [
{
"path": "/objectManage",
"component": "/platformManage/objectManage",
"hidden": 0,
"isShow": "0",
"meta": {
"title": "对象管理"
},
"children": [
{
"path": "organManage",
"component": "/platformManage/objectManage/organManage",
"hidden": 0,
"isShow": "0",
"meta": {
"title": "机构管理"
}
},
{
"path": "branchManage",
"component": "/platformManage/objectManage/branchManage",
"hidden": "1",
"isShow": 0,
"meta": {
"title": "部门管理"
}
},
{
"path": "userManage",
"component": "/platformManage/objectManage/userManage",
"hidden": "1",
"isShow": "0",
"meta": {
"title": "用户管理"
}
},
{
"path": "menuManage",
"component": "/platformManage/objectManage/menuManage",
"hidden": "1",
"isShow": "0",
"meta": {
"title": "菜单管理"
}
},
{
"path": "submitManage",
"component": "/platformManage/objectManage/submitManage",
"hidden": "1",
"isShow": "0",
"meta": {
"title": "报送菜单管理"
}
}
]
},
{
"path": "/powerManage",
"component": "/platformManage/powerManage",
"hidden": "1",
"isShow": "0",
"meta": {
"title": "权限管理"
},
"children": [
{
"path": "resourceAllocation",
"component": "/platformManage/powerManage/resourceAllocation",
"hidden": "1",
"isShow": "0",
"meta": {
"title": "资源分配"
}
},
{
"path": "dataAllocation",
"component": "/platformManage/powerManage/dataAllocation",
"hidden": "1",
"isShow": "0",
"meta": {
"title": "数据分配"
}
}
]
}
]
}
]
重点来了,我们看下这个后端给的路由表,component属性返回的是字符串,需要我们把它转换成() => import(’@/views/XX/XX’)这种格式的才行。
export function rFormat(routers) {
// 简单检查是否是可以处理的数据
if (!(routers instanceof Array)) {
return false
}
// 处理后的容器
const fmRouters = []
routers.forEach(router => {
const path = router.path
const component = router.component
const name = router.name
const hidden = Boolean(router.hidden)
let children = router.children
const meta = router.meta
const isShow = Boolean(router.isShow)
const redirect = router.redirect
console.log("component:::", component)
// 如果有子组件,递归处理
if (children && children instanceof Array) {
children = rFormat(children)
}
const fmRouter = {
path: path,
component(resolve) {
// 拼出相对路径,由于component无法识别变量
// 利用Webpack 的 Code-Splitting 功能
if (router.component === 'Layout') {
// Layout作为特殊组件处理,当然后端也可以写成'/layout/Layout.vue
require(['@/layout'], resolve)
} else {
// '@/views'要拼接进去,组件直接返回'@/views/xxxx/xxx.vue',然后require([compoent],resolve)会报错
require(['@/views' + component], resolve)
}
},
name: name,
hidden: hidden,
children: children,
meta: meta,
isShow: isShow,
redirect: redirect
}
fmRouters.push(fmRouter)
})
return fmRouters
}
//保留的基础路由
export const constantRoutes = [
{
path: '/',
component: Layout,
redirect: '/dashboard',
name: 'Dashboard',
hidden: true,
children: [{
path: 'dashboard',
component: () => import('@/views/dashboard/index')
}]
},
{ path: '*', redirect: '/dashboard', hidden: true },
{
path: '/login',
component: () => import('@/views/login/index'),
hidden: true
},
{
path: '/404',
component: () => import('@/views/404'),
hidden: true
},
]
const createRouter = () => new Router({
scrollBehavior: () => ({ y: 0 }),
routes: constantRoutes,
// mode: 'history',
})
const router = createRouter()
路由导航守卫
逻辑:
导航守卫中要做的事就是判断用户是否登录,没登录就去登录,登录完就去获取用户信息。获取用户信息这一步就会拿到用户的信息(姓名,角色,权限[url/element/菜单])。所以“拿到路由json数据,转换成vue可用路由,添加到当前路由”这波操作就放到登录成功后获取用户信息这里完成即可。
参考文献中是在此处判断是否登录成功的逻辑,如果你项目vuex中已经有GetInfo这个方法,在此处可以使用store.dispatch(‘GetInfo’),就是获取用户信息的动作,但在我项目中获取路由表是一个单独接口所以直接在这里调了。
let asyncRouter//用来获取后台拿到的路由
// 使用 router.beforeEach 注册一个全局前置守卫,判断用户是否登陆
router.beforeEach((to, from, next) => {
if (to.path === '/login') {
next();
} else {
//let token = store.state.user.token
//let user=store.state.user.name
//if (token === 'null' || token === ''||token === undefined) {
// if (!sessionStorage.getItem('user')) {
//next('/login');
// } else {
// store.dispatch("user/getInfo")
// next();
//}
let userRouter = get('USER_ROUTER')
if (!asyncRouter) {
if (!userRouter) {
let params = {name: "admin"}
getUserRouters(params).then((res) => {
asyncRouter = res.data.data
save('USER_ROUTER', asyncRouter)
go(to, next)
}).catch(err => { console.error(err) })
} else {
asyncRouter = userRouter
go(to, next)
}
} else {
next()
}
}
});
获取菜单权限路由表后,会保存在名为USER_ROUTER的localStorage里,此时即可对asyncRouter进行格式转换,并将转换后的表新增到路由的routes里就完成了。
function go (to, next) {
asyncRouter = rFormat(asyncRouter)
router.addRoutes(asyncRouter)
asyncRouter.forEach((item, index) => {
router.options.routes.push(item)
})
next({...to, replace: true})
console.log("LLLL:", router)
}
function save (name, data) {
localStorage.setItem(name, JSON.stringify(data))
}
function get (name) {
return JSON.parse(localStorage.getItem(name))
}
export default router
本人再次发表声明:参考文献:http://www.devopser.org/articles/2019/04/29/1556524856420.html,对参考文献的作者‘罐头鱼 - devopser”表示由衷的感谢!感谢这个开源的好时代,前人栽树,后人乘凉!