提示
其实当前内容是对前面《二、界面控制的补充》
# 路由表
前端根据 roles 去向后端请求可访问的路由表,然后将后端返回路由表和本地的组件映射到一起
{
"rights": [
{
"id": 103,
"authName": "⻆⾊管理",
"icon": "icon-tijikongjian",
"componentName": "roles",
"children": [
{
"id": 111,
"authName": "⻆⾊列表",
"path": "rolesList",
"componentName": "rolesList",
"rights": ["view", "edit", "add", "delete"]
}
]
},
{
"id": 101,
"authName": "商品管理",
"icon": "icon-shangpin",
"componentName": "goods",
"children": [
{
"id": 104,
"authName": "商品列表",
"path": "goodsList",
"componentName": "goodsList",
"rights": ["view", "edit", "add", "delete"]
},
{
"id": 121,
"authName": "商品分类",
"path": "categories",
"componentName": "categories",
"rights": ["view", "edit", "add", "delete"]
}
]
}
]
}
# 一、动态路由
# 1、结构
├── router
├── index.js
├── limits.js # 路由控制
# 2、路由信息
注意
关于菜单栏的动态路由实现,前提是一定要有一个 children
当前我们的仅仅是解决了二级路由,如果后端传来一级路由、多级路由就呵呵了 😂。
终极方案:可以参考 vue-element-admin 的动态路由实现
- router/index.js
const routes = [
{
path: '/',
name: '首页',
component: () => import('../layout'),
redirect: '/dashboard',
children: [
// 登录初次显示
{
path: '/dashboard',
name: '首页',
component: () => import('../views/index/index')
},
// 其他动态路由的存放位置
// ……
]
},
{
path: '/login',
component: () => import('@/views/login/index'),
},
{
path: '/404',
component: () => import('@/views/404'),
}
{ path: '*', redirect: '/404', hidden: true }
]
const router = createRouter({
routes
})
export default router
# 二、核心实现
- main.js
// 全局使用
import '@/router/limits.js'
- router/limits.js
import router from '@/router/index'
import store from '@/store'
// 一、导航守卫
const whiteList = ['/login', '/register']
router.beforeEach((to, from, next) => {
if (whiteList.includes(to.path)) {
next()
} else {
const token = sessionStorage.getItem('token')
if (!token) {
next('/login')
} else {
next()
}
}
})
# 方式 1:映射
优点:
component 的命名归前端管理,不用担心与后端命名不一致的问题
缺点:
不方便,要手动写路由规则
// 二、动态路由
// 1、菜单对象转路由对象
// 路由规则
const userRule = { path: '/users', component: Users }
const roleRule = { path: '/roles', component: Roles }
const goodsRule = { path: '/goods', component: GoodsList }
const categoryRule = { path: '/categories', component: GoodsCate }
// 登录请求path路由 与 路由规则 的映射🚩
const ruleMapping = {
users: userRule,
roles: roleRule,
goods: goodsRule,
categories: categoryRule
}
// 2、动态绑定路由
// 根据用户权限,设置动态路由规则
export function initDynamicRoutes() {
console.log(router)
// 路由中定义的【基础路由】(数组✨)
const currentRoutes = router.options.routes
// 服务器返回的数据(json数据)
const rightList = $store.state.rightList
rightList.forEach((item) => {
// 获取其中children的【二级路由】(数组✨)
item.children.forEach((menu) => {
// ①、动态添加二级路由🚩
const temp1 = ruleMapping[menu.path]
// ②、动态添加按钮权限
temp1.meta = menu.rights // 利用路由元信息附加上权限信息(备用👏)
currentRoutes[0].children.push(temp1) // 这里的下标要将动态路由存放的位置
})
})
// 正式重置路由
currentRoutes.forEach((item) => {
router.addRoutes(item)
})
}
# 方式 2:函数封装
优点:
方便快捷
缺点:
component 命名归后端管理,前端要提前知道后端定义的 menu.component。
// 二、动态路由
// 1、菜单对象转路由对象
const menuToRoute = (item, menu) => {
let route = {
name: menu.authName,
path: menu.path,
component: () => import(`@/views/${item.component}/${menu.component}.vue`)
meta: {
// ②、动态添加按钮权限
rights: menu.rights // 利用路由元信息附加上权限信息(备用👏)
}
}
return route
}
// 2、动态绑定路由
// 根据用户权限,设置动态路由规则
export function initDynamicRoutes() {
console.log(router)
// 路由中定义的【基础路由】(数组✨)
const currentRoutes = router.options.routes
// 服务器返回的数据(json数据)
const rightList = $store.state.rightList
rightList.forEach((item) => {
// 获取其中children的【二级路由】(数组✨)
item.children.forEach((menu) => {
// ①、动态添加二级路由🚩
const temp1 = menuToRoute(item, menu)
currentRoutes[0].children.push(temp1) // 这里的下标要将动态路由存放的位置
})
})
// 正式重置路由
currentRoutes.forEach((item) => {
router.addRoutes(item)
})
}