最近做项目时,优化了一个权限动态路由。
旧的动态路由实现方式,由后台直接返回路由列表,并且路由也是由后台返回。然后前端去生成路由文件,有时候点击某个栏目时,它的路由还没生成,导致页面无法进入。
旧方式后台返回的菜单形式:
[
{
menuCode: "001"
menuName: "About/介绍"
},
{
menuCode: "001001"
menuName: "AboutUs/关于我们"
},
{
menuCode: "001002"
menuName: "ContactUs/联系我们"
},
{
menuCode: "002"
menuName: "Product/产品"
},
{
menuCode: "002001"
menuName: "Type1/类别一"
},
{
menuCode: "002002"
menuName: "Type2/类别二"
},
...
]
因为 后台没有生成带结构的json格式,导致前台生成路由的时候,需要循环历遍,比较麻烦,而且会出现路由未渲染完就进去了页面,导致页面空白(具体情况跟项目实现方式有关系)。
为了路由简单化,想路由通过前端控制,后台返回一个权限列表,通过跟前端的动态路由去比较,然后控制路由的显示。
新的实现方式:
router.js:
// 静态路由
const staticRoutes = [
{
path: '/login',
name: 'Login',
component: Login,
meta: { title: '登录' }
}
]
// 动态路由
export const asyncRoutes = [
{
path: '/About',
name: 'About',
component: () => import('../layout/index')
children: [
{
path: '/About/AboutUs',
component: () => import('../View/about/aboutUs'),
name: 'aboutUs'
},
{
path: '/About/ContactUs',
component: () => import('../View/about/contactUs'),
name: 'contactUs'
},
]
},
{
path: '/Product',
name: 'Product',
component: () => import('../layout/index'),
children: [
{
path: '/Product/Type1',
component: () => import('../View/product/type1'),
name: 'Type1'
},
{
path: '/Product/Type2',
component: () => import('../View/product/type2'),
name: 'Type2'
},
]
}
]
...
store/modules/permission.js
import { asyncRoutes } from '../../router'
/**
* 是否有某个路由
* @param paths
* @param route
*/
function hasMenu(paths, route) {
return paths.some(path => route.path == path)
}
/**
* 历遍路由
* @param routes asyncRoutes
* @param roleMenus
*/
export function filterAsyncRoutes(routes, roleMenus) {
const res = []
routes.forEach(route => {
const item = { ...route }
if (hasMenu(roleMenus, item)) {
if (item.children) {
item.children = filterAsyncRoutes(item.children, roleMenus)
}
res.push(item)
}
})
return res
}
const state = {
dynamicRoutes: [],
}
const mutations = {
SET_ROUTES: (state, routes) => {
state.dynamicRoutes = routes
}
}
const actions = {
async generateRoutes({ commit }) {
// 模拟后台返过来的登录用户路由列表
let res = "/About,/About/AboutUs,/Product,/Product/Type2"
let roleMenu = res?.split(',')
let accessedRoutes
accessedRoutes = filterAsyncRoutes(asyncRoutes, roleMenu)
commit('SET_ROUTES', accessedRoutes)
}
}
然后页面可以直接通过Store里边的dynamicRoutes把该用户的路由渲染出来。