其他router相关内容索引
序号 | 内容 |
1 | vue router 整合引入 |
2 | vue router 模块化开发 |
3 | vue router 动态路由及菜单实现之一 |
4 | vue router 动态路由及菜单实现之二 |
5 | vue router 动态路由及菜单实现问题汇总 |
6 | vue el-menu多级菜单递归 |
7 | vue router 懒加载常见写法 |
之前将路由引入,按模块简单划分后,准备将路由和菜单结合起来。发现需要前端维护一遍菜单,后端也要维护一遍菜单,这就有点蛋疼。每次后端改了一点,前端也要相应的改一波配置。
看了一波其他大神的,也是用两种方式实现的,但具体的细节方面很少有提到,router这种东西看不到具体的路径就会很懵逼。
vue router 动态路由实现之一
router.addRoutes
要动态添加路由,主要用到的方法就是router.addRoutes
但这个方法在官方api的解释:
没错,就是这么简单,这个看第一眼就知道要苦了。但该用还得用嘛,要踩的坑肯定要踩的。用法看起来很简单,就只要符合RouterConfig的格式数组就可以了。
就是像这样的数组,直接传进去就可以了。手写代码有点不好的就是容易错了找不到,所以如果不是为了学习,还是复制粘贴的效率高些。
router.js的改造
router.js路由文件的改造思路:
1、加载静态路由,用户能直接访问的路由,不需要判断权限就需要直接展示的。
2、加载动态路由,需要判断用户权限,需要从后台传过来,需要动态生成菜单的。
router.js
const router = new VueRouter({
mode: 'history',
base: process.env.BASE_URL,
scrollBehavior: () => ({ y: 0 }),
routes: []
})
/* 加载可以直接访问的路由 */
router.addRoutes(constantRoutes1);
/* 加载后端路由 */
router.addRoutes(filterAsyncRouter(asyncRoutes));
/* 加载 404 */
router.addRoutes(constantRoutes2);
// 路由变化时
router.beforeEach((to, from, next) => {
if (document.title !== to.meta.title) {
document.title = to.meta.title;
}
next()
})
export default router
新建 constrouter.js
/* constantRoutes静态路由,所有用户均可访问 */
export const constantRoutes1 = [
{
path: '/',
redirect: '/login'
},
// 系统登录
{
path: '/login',
name: 'Login',
component: () => import('@/layout/login'),
meta: {
title: '用户登录'
}
},
}
/* constantRoutes静态路由,所有用户均可访问 */
export const constantRoutes2 = [
{
path: "/system",
redirect: '/system',
},
...ERROR,
{
path: '/*',
redirect: '/404',
},
]
动态生成路由
动态生成路由最关键的是怎么将 component 后面的参数由后台传递过来,并进行转化成router可以识别的样子,毕竟后台不可能传这样的过来,这个也不是一个字符串。
() => import('@/layout/login'),
这里先看一眼之前的菜单文件,这里已经把component参数给加好了,如果直接用el-menu的话,这个参数用不上。role也是新加的,后续留着判断菜单权限用。
const asyncRoutes = [
{
"path": "/system",
"name": 'SystemIndex',
"component": "system",
"meta": {
"title": "系统管理",
"icon": "el-icon-setting",
"role": [
"admin"
]
},
"children": [
{
"path": "role",
"component": "system/role",
"meta": {
"title": "角色管理",
"icon": "el-icon-star-on",
"role": [
"admin"
]
}
},
{
"path": "user",
"component": "system/user",
"meta": {
"title": "用户管理",
"icon": "el-icon-user-solid",
"role": [
"admin"
]
}
},
{
"path": "menu",
"component": "system/menu",
"meta": {
"title": "菜单管理",
"icon": "el-icon-menu",
"role": [
"admin"
]
}
},
{
"path": "trans",
"component": "system/trans",
"meta": {
"title": "多系统",
"icon": "el-icon-s-opportunity",
"role": [
"admin"
]
}
},
{
"path": "test",
"component": "system/home",
"meta": {
"title": "系统测试",
"icon": "el-icon-success",
"role": [
"admin"
]
}
}
]
},
]}
注意:这里的component千万别手贱写个components。多个s,component匹配不上,还找不到为什么真的会怀疑人生。
现在需要将这里的component的字符串参数转化一下
//遍历后台传来的路由字符串,转换为组件对象
export function filterAsyncRouter(asyncRouterMap) {
const accessedRouters = asyncRouterMap.filter(route => {
if (route.component) {
if (route.component === 'system') {
route.component = system
} else {
// console.log("load:" + loadView(route.component));
route.component = loadView(route.component)
// console.log("import:" + __import(route.component));
// route.component = __import(route.component)
}
}
if (route.children && route.children.length) {
route.children = filterAsyncRouter(route.children)
}
return true
})
return accessedRouters
}
/* 加载路由组件,两种方式均可 */
const loadView = (view) => { // 路由懒加载
// return (resolve) => require([`@/views/${view}`], resolve)
return () => import('@/views/' + view)
}
这里要规划好应用页面的路径,不然就得多加判断了。
查看动态路由
这块可以说是最关键了,不然这个生成完了那里写错了,为什么找不到路径,总是404就会很难受。
在官网上找到了这个方法
$route.matched
类型: Array<RouteRecord>
一个数组,包含当前路由的所有嵌套路径片段的路由记录 。路由记录就是 routes 配置数组中的对象副本 (还有在 children 数组)。
当 URL 为 /foo/bar,$route.matched 将会是一个包含从上到下的所有对象 (副本)。
找了半天的路径在router.matcher中发现了。静态和动态路由都使用addrouters方法添加,所有的path就会addRouters中的Scopes中转成一个pathList。
整个router关键信息的位置,这里面还有其他的一些 alias、match、nameMap,还有对应的redirect。所以在后续后台传过来的东西中
这些也是可以包含使用了。
el-menu动态生成菜单
动态路由完成了,前端基本上没什么需要改的,el-menu 加上router属性,index属性将会用于激活route action的path
官方原文
whether vue-router mode is activated. If true, index will be used as 'path' to activate the route action
这里就没有写递归了,直接 for和if写了三层判断,一般菜单也不会超过三层。
最终效果如下