/*
authority: 用户角色
component: 前端根据这个组建文件地址
*/
{
"data": [
{
"id": 1,
"name": "首页",
"path": "/home",
"pid": 0,
"authority": "admin",
"component": "home/index"
},
{
"id": 2,
"name": "系统管理",
"path": "/system",
"pid": 0,
"authority": "admin",
"component": "layout",
"children": [
{
"id": 3,
"name": "角色权限",
"path": "/userjurisdiction",
"pid": 2,
"authority": "admin",
"component": "system/userjurisdiction"
},
{
"id": 4,
"name": "菜单管理",
"path": "/menumanagement",
"pid": 2,
"authority": "admin",
"component": "system/menumanagement"
}
]
}
]
}
router/index.js
// 开发环境不使用懒加载
const _import = require('./import-' + process.env.NODE_ENV)
// 全局路由
export const constantRoutes = [
{ path: '/', redirect: '/login' },
{ path: '/login', component: _import('login/index'), name: 'Login', meta: { title: '登录' } }
]
// 主入口路由
export const mainRoutes = {
path: '/surHome',
component: layout,
redirect: { path: '/home' },
children: []
}
const router = new VueRouter({
mode: 'hash',
mode: 'history',
scrollBehavior: () => ({ y: 0 }),
isAddDynamicMenuRoutes: false, // 是否已经添加动态(菜单)路由
routes: constantRoutes.concat(mainRoutes)
})
// 路由白名单, 可以在这里添加不需要权限的地址
const whiteList = ['/login']
// 添加动态(菜单)路由
router.beforeEach((to, from, next) => {
let token = getToken()
if (!token || !/\S/.test(token)) { // 判断token为空
// 这一步判断是不是白名单地址, 如果是则next, 不是将会跳转到/login
if (whiteList.indexOf(to.path) !== -1) {
next()
} else {
// 这一步很重要, 一定要排除当前/login地址, 否则会陷入无限循环
to.path === '/login' ? next() : next({ path: '/login' })
}
} else if (router.options.isAddDynamicMenuRoutes) { // 如果已经包含权限
next()
} else { // token不为空走进页面请求菜单
getNav({ id: JSON.parse(sessionStorage.getItem('user')).id }).then(response => {
if (response.status === 200) {
store.state.user.menuList = response.data.data
// 路由转换成组件地址(过滤出没有children的对象(扁平化数组))
const RoutesList = getAsyncRoutes(Objectlist(flattening(response.data.data)))
mainRoutes.children = RoutesList
router.addRoute(mainRoutes)
router.options.isAddDynamicMenuRoutes = true
next({ ...to, replace: true })
}
})
}
})
export default router
router/import-development.js
/*
file: 路由表里面的component
*/
module.exports = file => require('@/views/' + file + '.vue').default
router/import-production.js
/*
file: 路由表里面的component
*/
module.exports = file => () => import('@/views/' + file + '.vue')
router/asyncRouter.js
// Layout 组件是项目中的主页面,切换路由时,仅切换Layout中的组件
import Layout from '@/components/layout'
// 开发环境不使用懒加载
const _import = require('./import-' + process.env.NODE_ENV)
// 过滤路由方法封装
export function getAsyncRoutes(asyncRouterMap) { //遍历后台传来的路由字符串,转换为组件对象
const accessedRouters = asyncRouterMap.filter(route => {
if (route.component) {
route.component = _import(route.component)
}
if (route.children && route.children.length) {
route.children = getAsyncRoutes(route.children)
}
return true
})
return accessedRouters
}
// 扁平化数组对象
export function flattening(arr) {
return arr.reduce((result, item) => {
return result.concat(item, (Array.isArray(item.children) ? flattening(item.children) : []));
}, [])
}
// 将带有children的对象过滤出去
export const Objectlist = (arr) => {
return arr.filter(child => !child.children)
}
至于vue菜单怎么写,请看另一篇文章vue菜单递归