做后台管理系统,我们经常需要对各个用户进行权限的管理,不同权限的用户所能看到的页面也不相同,那么我们应该怎么做呢。下面,我说说我近期的实战案例。
一、编写路由
写路由这一步正常写就行,没什么特别的地方
{
path: "/",
redirect: "/login",
children: []
},
{
path: "/login",
component: Login,
name: "",
meta: {
},
children: []
},
{
path: "/index",
name: "index",
component: Layout,
componentname: "home",
meta: {
requireAuth: true
},
redirect: "/index/test1",
children: [
{
path: "/index/test1",
name:"test1",
componentname: "test1",
component: Test1,
children: []
},
{
path: "/index/test2",
name:"test2",
componentname: "test2",
component: Test2,
children: []
}
]
},
{
path: "/box",
name: "box",
component: Layout,
componentname: "home",
redirect: "/box/test1",
children: [
{
path: "/box/test1",
name: "box1",
componentname: "box1",
component: Box1,
children: []
},
{
path: "/box/test2",
name:"box2",
componentname: "box2",
component: Box2,
children: []
}
]
},
路由怎么写就不过多赘述了,相信会看这篇文章的,路由也都会写。
二、将路由信息交由后台进行保存配置
这也很简单,将你配好的各种路由对应哪个页面的信息发给后端就行,后端需要进行配置,用于在不同权限的人登录时返回你不同的有权限的路由信息。
返回信息有多种,可以使name,也可以是数字,这个没有固定的,自认为自己怎么好弄怎么来,我一般直接让后端直接返给我有权限的路径数组。
三、在vuex中写动态添加路由的方法
import { defaultRouter, addRouter } from "@/router/index";
import lodash from "lodash";
const routerData = {
state: {
routers: [],
addRouters: []
},
mutations: {
setRouters: (state, routers) => {
state.addRouters = routers; // 保存动态路由用来addRouter
state.routers = defaultRouter.concat(routers); // 所有有权限的路由表,用来生成菜单列表
}
},
actions: {
newRoutes({ commit }, options) {
if (!options.menus) { //判断调用的时候参数中有没有路由信息
commit("setRouters", []);
return;
}
// 通过递归路由表,删除掉没有权限的路由
function eachSelect(routers, componentname) {
var newrouter = lodash.cloneDeep(routers);
newrouter.forEach(item => {
if (item && item.children && item.children.length) {
eachSelect(
routers[routers.findIndex(v => v.name === item.name)].children,
componentname
);
}
if (
componentname.indexOf(item.path) == -1 &&
routers[routers.findIndex(v => v.name === item.name)].children
.length == 0
) {
routers.splice(
routers.findIndex(v => v.name === item.name),
1
);
}
});
}
function getMenuCode(menu) {
var menus = [];
if (menu && menu.length > 0) {
menu.forEach(element => {
menus.push(element.Url);
if (element.Childrens && element.Childrens.length > 0) {
menus = menus.concat(getMenuCode(element.Childrens));
} else {
return [];
}
});
}
return menus;
}
var menus = getMenuCode(options.menus);
eachSelect(defaultRouter, menus);
commit("setRouters", addRouter);
}
}
};
export default routerData;
执行顺序:newRoutes=>路由无值=>getMenuCode=>eachSelect=>commit
想要看懂流程请先了解findIndex,indexOf,splice
四、登录时保存路由数据
login() {
let that = this;
var data = {
Tel: that.tel,
VerificationCode: that.verificationCode
};
this.loading = true; //改变loading状态
Sign(data).then(res => { //调用登录接口
if (res.Status) { //成功获取参数后
that.$store.dispatch("setToken", "asdasdasdsad"); //随便写的token验证,可以忽略
that.$store.dispatch("setRole", { //调用vuex中的方法,保存用户信息
UserID: res.Data.UserId,
Menus: res.Data.Menus
});
that.$router.push({ path: "/index" });
this.$notify({
title: "成功",
message: "登录成功",
type: "success"
});
} else {
this.$notify.error({
title: "错误",
message: res.Message
});
}
this.loading = false;
})
.catch(err => {
this.$notify.error({
title: "错误",
message: "参数获取失败,请重试"
});
this.loading = false;
});
},
保存用户信息方法
setRole(state, options) {
// 切换角色,测试权限管理
state.info = {
UserID: options.UserID,
Menus: options.Menus
};
sessionStorage.setItem("info", JSON.stringify(store.getters.info)); //保存用户信息到缓存
store.dispatch("newRoutes", { //调用动态生成路由方法
menus: options.Menus,
role: options.RoleName
});
router.addRoutes(store.getters.addRouters);//这里是添加无需验证的动态路由
},
五、在main.js中设置路由守卫,防止刷新路由消失
router.beforeEach((to, from, next) => {
if (store.getters.token) { //判断是否登录
store.dispatch("setToken", store.getters.token);
if (to.path === "/login") {
Cookies.remove("token");
next();
return;
} else {
if (to.matched.length) { //判断输入的路由在路由表中是否存在
!(async function getAddRouters() {
await store.dispatch("newRoutes", { //动态设置路由
menus: store.getters.info.Menus,
role: store.getters.info.RoleName
});
})();
next();
} else {
next({
path: "/404"
});
}
}
} else {
if (to.path === "/login") {
next();
} else {
next({
path: "/login"
});
}
}
});
在vuex中获取info的问题
state: {
info: JSON.parse(sessionStorage.getItem("info")) || "", // 从缓存中取或者是为空(登录或者未登录)
},
六、流程简述
1、用户登录
2、保存返回的用户信息和权限路由(vuex和缓存)
3、触发路由守卫,调用路由筛选
4、根据数据,删除无权限的路由信息
5、返回筛选后的路由信息
6、渲染路由和页面
7、刷新触发3-6