目录
权限
1路由与菜单权限(不同身份访问不同的页面)
1.1先放完整代码
<1>代码放在登录的页面(一般是login.vue)发送登录接口的方法里(调用接口方法不限制)
主要把,从接口拿到的role,存储在本地和调用计算路由的函数(先存储在调用)
methods: {
//登录
loginHandle() {
this.$refs.loginDom.validate(async valid => {
if (valid) {
//发送登录接口ajax
let res = await usersCheckLogin(this.loginForm);
let { code, msg, token, role } = res.data;
if (code === 0) {
//把token存储到本地存储
localStorage.setItem("token", token);
//把role存档本地存储
localStorage.setItem("role", role);
console.log(role);
//调用计算路由的函数
calcRouterHandle();
//跳转到后台首页
this.$router.push("/home");
} else {
this.$message.error(msg);
}
}
});
<2>代码放在router的index.js中(需要配置权限的路由),灵活的写里面的
//通过计算访问--动态路由
const calcRouters = [
//商品管理 super可以访问商品列表和商品分类,normal只能访问商品列表
{
path: "/goods",
component: Layout,//布局组件
redirect: "/goods/goods-list",
meta: { title: "商品管理", role: ['super', 'normal'], icon: "el-icon-goods" },
//如果title前有小图标则写入icon,没有可以忽略不计
children: [
{
path: "/goods/goods-list",
component: () => import("@/views/goods/GoodsList.vue"),
meta: { title: "商品列表", role: ['super', 'normal'] },
},
{
path: "/goods/goods-cate",
component: () => import("@/views/goods/GoodsCate.vue"),
meta: { title: "商品分类", role: ['super'] },
}
]
},
//店铺管理 只能super访问
{
path: "/shop",
component: Layout,//布局组件
redirect: "/shop",
meta: { title: "店铺管理", role: ['super'], icon: "el-icon-s-shop" },
children: [
{
path: "/",
meta: { role: ['super'] },
component: () => import("@/views/shop/Shop.vue")
}
]
},
]
const router = new VueRouter({
routes
})
//根据role去能访问的计算路由,在登录页面,发送登录接口函数里,调用
export const calcRouterHandle = () => {
let role = localStorage.getItem("role");
if (!role) return;
//一级菜单的权限
let r = calcRouters.filter(item => {
// console.log(item.meta)
if (item.meta && item.meta.role && item.meta.role.includes(role)) {
return item;
}
})
//二级菜单
r.forEach(val => {
if (val.children) {//有二级菜单
val.children = val.children.filter(v => {
if (v.meta && v.meta.role && v.meta.role.includes(role)) {
return v;
}
})
}
})
//把计算出来的路由存储到本地存储
localStorage.setItem("meun", JSON.stringify(r));
//把动态路由添加到路由中
r.forEach(val => {
router.addRoute(val)
})
}
export default router
<3>退出登录时刷新页面(这里用了elementui的组件),灵活使用
重点在切换账号或者退出登录时,this.$router.go(0),放到你自己的退出登录的地方就行
<el-dropdown-menu slot="dropdown">
<el-dropdown-item command="loginOut">切换账号</el-dropdown-item>
</el-dropdown-menu>
//handleCommand为点击事件触发的方法
methods: {
handleCommand(command) {
if (command === "loginOut") {
//切换账号
localStorage.clear();
this.$router.push("/login");
//刷新页面 解决addRoues的bug
this.$router.go(0);
}
}
}
<4>代码放在导航的.vue中,写如图的代码的地方里
<template>
<div class="left-nav">
<div class="left-nav-logo">
</div>
<el-menu
:default-active="$route.path"
background-color="#161c64"
text-color="#fff"
active-text-color="#f33"
unique-opened
router
>
//每一个权限都可以看见后台首页,于是把后台首页写死
<el-menu-item index="/home">
<i class="el-icon-s-home"></i>
<span slot="title">后台首页</span>
</el-menu-item>
//区分了权限的页面,动态绑定
<template v-for="(val,i) in navArr">
<!-- 展开:点击之后可以展开的导航 -->
<el-submenu
:index="val.path"
:key="i"
v-if="val.children.length>1"
>
<template slot="title">
//如果title前有小图标,没有则省略
<i :class="val.meta.icon"></i>
<span>{{val.meta.title}}</span>
</template>
<el-menu-item-group>
<el-menu-item
:index="item.path"
v-for="(item,index) in val.children"
:key="index"
>{{item.meta.title}}</el-menu-item>
</el-menu-item-group>
</el-submenu>
<!-- 不展开 -->
<el-menu-item :index="val.path" :key="i" v-else>
<i :class="val.meta.icon"></i>
<span slot="title">{{val.meta.title}}</span>
</el-menu-item>
</template>
</el-menu>
</div>
</template>
<script>
export default {
data() {
return {
navArr: JSON.parse(localStorage.getItem("meun"))
};
},
};
</script>
1.2 详细讲解
第一步:在登录,获取接口成功后,把role存储到本地存储,application里,检查一下是否保存
第二步:把路由一分二,静态路由和动态路由
静态路由:如重定向页面、登录页面、后台首页是所有权限都能访问的
动态路由:根据权限划分的,具体代码上面有。逻辑就是:定义一个叫calcRouters的数组(const calcRouters[])存放路由对象。
第三步:在动态路由中配置meta:{role:['super','normal']}(具体的值根据后端接口来定)
第四步:在路由里面写一个计算路由的函数(export const calcRouterHandle()),在登录成功,路由保存之后调用。注意:函数要暴露,在登录页面使用时,先引入(import { calcRouterHandle } from "@/router";)
calcRouterHandle函数的作用1:从本地存储中,获取到已保存的路由。判断,如果权限不存在则停止之后的流程
calcRouterHandle函数的作用2:对存放动态路由的数组进行过滤,筛选符合条件的路由。
一级路由:判断:路由对象有meta,且meta中有role,且role符合权限,则筛选出此路由对象。
二级路由:子路由,要在一级路由的children里找,所以先判断是否有子路由(if (val.children))
calcRouterHandle函数的作用3:将计算出来的路由存储至本地存储,步骤六里的导航栏需要用
calcRouterHandle函数的作用4:把计算出来的路由添加到路由中,才能使用,addRoute是路由自带的方法,不用纠结直接用
第五步:退出登录的时候,刷新页面。因为addRoute有bug,假如已经登录超级管理员权限,在登录普通管理员权限时,是加在超级管理员权限之后,具有超级和普通权限,所以退出时要刷新。
第六步:导航栏/菜单栏的显示应与权限同步。
6.1:在第四步中已将路由存放至本地,所以直接获取
6.2:v-for并动态绑定,如果菜单可以展开有子路由,则注意绿色字体
6.3:如果字之前有小图标,可将小图标的名字存放路由的meta中,方便动态绑定
meta: { title: "商品管理", role: ['super', 'normal'], icon: "el-icon-goods" },
2按钮权限(不同身份访问相同的页面,使用的按钮操作不同)
从本地存储获取权限数据,并对按钮v-if设置权限,就可以了。
这里是,super权限可以使用,includes(role)判断role里是否包含super,
<el-button v-if="['super'].includes(role)" type="text"></el-button>
export default {
data() {
return {
role: localStorage.getItem("role")
}
}
}