vue路由动态配置

在后台系统这类的项目中,用户角色和权限的区分是不可分割的一部分需求。常见的用户权限区分形式有两种,一是前端请求接口拿到后台配置的用户权限信息;另一种是直接由前端来定义每种用户角色的权限页面,然后在生成对应的路由。今天我们来了解前端配置路由权限的方式。

角色权限页面配置

在配置角色对应的路由页面时,可以参考项目所用的前端框架导航组件的参数,我们以elment uimenu组件为例:可对审核方(Auditor)、供应商(Supplier)和需求方(Business)做如下配置:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
  const appMenuitem = {
// 审核方下拉选项(路由)菜单
Auditor: [
{
// icon: "el-icon-view", // operationLog userConfiguration
title: "基本配置",
index: "1",
subs: [
{
index: "dataOverview",
title: "数据概览"
}
]
},
{
// icon: "el-icon-view",
title: "需求审核",
index: "2",
subs: [
{
index: "demendManage",
title: "需求管理"
}
]
}
],
// 业务方下拉选项和路由
Business: [
{
title: "基本配置",
index: "1",
subs: [
{
index: "demandList",
title: "需求列表"
}
]
}
],
// 供应商
Supplier: [
{
title: "需求制作",
index: "1",
subs: [
{
index: "needList",
title: "需求列表"
}
]
}
]
};

这样配置后,所有用户角色的权限信息都在appMenuitem中,在项目的开发,我们可以按照配置的对象属性index(这里是可以由开发按自己的习惯约定)的值,如dataOverviewdemendManage等来建立页面。如图:
image

生成侧边菜单逻辑(需配置好路由router才能运行)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
<el-menu
background-color="#fff"
text-color="#222222"
theme="dark"
:default-active="onRoute"
:collapse="false"
router
>
<template v-for="(item, index) in items">
<!-- 有子选项 -->
<template v-if="item.subs && item.subs.length > 0">
<el-submenu :index="item.index" :key="index">
<template slot="title">
<i :class="item.icon"
></i>
<span>{{ item.title }}</span>
</template>
<el-menu-item-group>
<el-menu-item
v-for="(subItem, index2) in item.subs"
:key="index2"
:index="subItem.index"
>
<span>{{ subItem.title }}</span>
</el-menu-item>
</el-menu-item-group>
</el-submenu>
</template>
<!-- 无子选项 -->
<template v-else>
<el-menu-item :index="item.index" :key="item.index">
<i :class="item.icon"></i>
{{ item.title }}
</el-menu-item>
</template>
</template>
</el-menu>
1
this.items = appMenuitem[userMap[this.userInfo.role]];

手动配置上的工作就完成了。后面就是完成路由的动态生成了。

路由生成

首页配置在router.js中配置项目通用路由:

1
2
3
4
5
6
7
8
9
10
11
12
13
  let router = new Router({
routes: [
{
path: "/",
redirect: "/home",
},
{
path: "/login",
name: "login",
component: resolve => require(["../views/Login.vue"], resolve)
}
]
});

home是主路由,前面配置的路由页面均嵌套在其中。下面来看看生成其他路由的方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
  function initRouter() {
// 登录用户 角色 审核方 业务方 供应商
const userType = userMap[store.state.userInfo.role] || 'Auditor';
let subs = appMenuitem[userType],
children = [];
subs = subs
.map(c => c["subs"])
.forEach(sub => {
children = children.concat(sub);
});
children = children.map((child, index) => {
if (index == 0) {
return {
path: `/${child.index}`,
component: resolve =>
require([`@/views/${userType}/${child.index}.vue`], resolve)
};
}
return {
path: `/${child.index}`,
name: `${child.index}`,
component: resolve =>
require([`@/views/${userType}/${child.index}.vue`], resolve)
};
});
// 为了配置 菜单导航
children.unshift({
path: "/",
redirect: children[0].path
});
// console.log(children)
return children;

}

只要调用这个方法就可以生成,home的子级路由了。接下来我们可以通过router的APIaddRoutes完成路由的添加

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
  // 在页面不刷新的前提 避免重复生产动态路由
window.hasRoutes = false;

router.beforeEach((to, from, next) => {
// 路由卫士
if (to.path === "/login") {
// 请除登录信息
localStorage.removeItem("hasLogin");
}
let user = localStorage.getItem("hasLogin") == null;
// 这里store.state.userInfo.role 是后台返回来的 用户角色信息 role 取值 为 1 2 3 分别 对应前面的键值 Author...
if ((user|| !store.state.userInfo.role) && to.path !== "/login" ) {
// 登录信息失效 直接去登录页面
next({ path: "/login" });
} else {
// 获取动态路由
if (store.state.userInfo.role && !window.hasRoutes) {
// window.hasRoutes 为了简单,使用的全局变量 进入登录login.vue 页面也可以重置为false即可

// router 创建新的路由对象
let newRouter = new Router({
routes: [
{
path: "/",
redirect: "/home",
},
{
path: "/login",
name: "login",
component: resolve => require(["../views/Login.vue"], resolve)
}
]
})
let children = initRouter();
router.matcher = newRouter.matcher;
// 添加路由
router.addRoutes([
{
path: "/home",
// name: "home",
component: resolve => require(["@/views/Home.vue"], resolve),
children: children
}
]);
// 避免重复
window.hasRoutes = true;
// 这里 时在实际情况存在 切换登录对象的时候, 首次路由加载不成功,需要刷新, 我们 手动跳到 home 重新走下刚刚的逻辑
if(from.path == '/login') {
router.push({path:'/home'})
}else{
router.push({ path: to.path })
}
}
else {
next();
}
}
});

最后,前端配置生成动态路由的方法基本就是这样啦,这是我在项目中遇到的坑,希望有所帮助.

-------------本文结束感谢您的阅读-------------