首页>>前端>>Vue->vue router根据路由区分用户权限并生成动态侧边栏

vue router根据路由区分用户权限并生成动态侧边栏

时间:2023-11-29 本站 点击:0

背景

在管理后台系统中,vue-router 往往要承担更多的事情。

因为在管理后台,一个非常重要也非常常见的功能,就是用户权限的区分。一般用户,管理用户,超级管理员,审计用户等等。

针对不同的用户,既要做接口的检验,也要对页面的权限进行划分。

比如:

超级管理员拥有所有的权限,能查看所有的页面,能进行所有的操作

管理用户,则不能添加,删除,变更系统里的用户

审计用户,只能查看需要审计的内容,如系统操作日志等

以上种种,其实都是跟页面的展示,路由的访问,接口的校验强相关的。当前用户如果是审计用户,那么只能展示某些页面,如果是管理用户,那要隐藏某些页面。

另外,管理项目都有一套侧边栏作为不同功能页面的入口。

假设我们的路由和侧边栏是分开的逻辑,那么就有以下的问题:

每次更新一次路由,就要更新一次侧边栏,

路由中做了权限,侧边栏还要单独加一个权限管理的逻辑

这样会显得我们前端开发很呆板。

所以总结来说,vue-router 要实现这样的功能

挂载组件到页面

根据不同的用户角色,如:超级管理员,审计用户,普通用户等来做路由权限管理

根据路由生成复杂的侧边栏

那么,如何使用一套定义好的 router 来做到以上三个需求呢?

分析

首先,我们来细致的分析一下这三个需求有哪些具体需要

挂载组件到页面中

想必不用多说了,vue-router 本来就是做这个的

区分不同用户角色

用户角色一般是保存在数据库中,用户登录之后由后台的接口返回的,比如这个字段是user_role,那么这里怎么实现动态的路由区分呢?

首先,我们可以把这个字段存储在 vuex 中,这样可以做到全局访问,全局自动更新

其次,在 vue-router 的每一个路由对象中插入一个字段,比如叫permission,来记录当前这个路由能够被谁访问,如permission: [0,1,2]

根据user_rolepermission来匹配筛选所有的路由,筛选后的结果,就是当前用户能够访问的路由

使用 vue-router 的方法将得到的路由添加到项目的路由对象里,地址

生成复杂的侧边栏

侧边栏是管理后台都有的功能,这里参考 vue-element-admin 的实现。 本质上 router 是一个javascript 的数组对象,遍历这个对象,利用 elementui 的 el-menu 组件来生成侧边栏就可以了。

如果 router 变化了 那么侧边栏也会随之变化。

实现

我们先定义一个整体的 router 对象,这个对象是整个项目里所有的页面路由,也是超级管理员默认的访问权限,这个对象的每一个route 对象,都可以含有如下的属性或者方法:

hidden: 是否显示在侧边栏

name: 侧边栏对应的文字内容,当name不存在,则children中的路由为一级路由,否则为二级路由,侧边栏最多显示到二级路由

iconName:侧边栏的 icon 图标

permission:可以访问辞路由的用户列表

//routerData.jsconstrouter1=[{path:'/',redirect:'/homepage',hidden:true,meta:{permission:[1,2,3]}},{path:'/homepage',meta:{permission:[1,2,3]},redirect:'/homepage/dashboard',component:layout,children:[{path:'dashboard',name:'安全状态监控',meta:{iconName:'icon-erji-loudongsaomiaoguanli',permission:[1,2,3]},component:()=>import('../views/dashboard/index.vue'),},]},{path:'/assetManagement',name:'资产管理',meta:{iconName:'icon-erji-loudongsaomiaoguanli',permission:[1,2,3]},redirect:'/assetManagement/assetList',component:layout,children:[{path:'assetList',name:'资产列表',meta:{permission:[1,2,3]},component:()=>import('../views/assetManagement/assetList.vue'),},{path:'assetDetail',name:'资产详情',meta:{permission:[1,2,3]},component:()=>import('../views/assetManagement/assetList.vue'),},]},{path:'*',redirect:'/',hidden:true,meta:{permission:[1,2,3]},}]exportcommonRoute=[{path:'/login',component:()=>import('@/views/login.vue'),hidden:true,meta:{permission:[1,2,3]},}]exportdefaultrouter1

然后我们在 index.js 中实现 router 的挂载

//router/index.jsimportVuefrom'vue'importVueRouterfrom'vue-router'import{commonRoute}from'./routerData'importlayoutfrom'@/layout'Vue.use(VueRouter)exportconstpermissionRouter=function(router,roleType){returnrouter.filter(item=>{if(item.children)item.children=permissionRouter(item.children)returnitem.meta.permission.includes(roleType)})}exportdefaultnewVueRouter({commonRoute})

当用户登录后,我们先获取用户的角色,然后放到 vuex 中存储后,就可以根据用户角色,动态的计算出权限路由了

importstorefrom'@/store'importrouter1from'@/router/routerData'importrouter,{permissionRouter}from'@/router/index'constroleType=store.getters.user_roleconstpermissionRouterList=permissionRouter(router1,roleType)router.addRoute(permissionRouterList)

到这里整个 router 就写好了,router 接下来就可以准备动态的生成侧边栏,侧边栏逻辑复杂一点,所以我也是拆成了三个文件

这是文件的目录:

sidebar├──index.vue├──item.vue├──sidebarItem.vue

然后来实现动态侧边栏的逻辑

//index.vue<template><divclass="sidebar-container"><el-menu:unique-opened="true":collapse-transition="false"background-color="rgba(0,0,0,0)":default-active="activeMenu"><sidebar-itemv-for="(item,index)inpermissionRouterList":key="index":item="item"/></el-menu></div></template><script>importstorefrom'@/store'importrouter1from'@/router/routerData'import{permissionRouter}from'@/router/index'importSidebarItemfrom'./sidebarItem.vue'exportdefault{components:{SidebarItem},computed:{activeMenu(){returnthis.$route.path},permissionRouterList(){constroleType=store.getters.user_rolereturnpermissionRouter(router1,roleType)}}}</script>
//item.vue<template><el-menu-item:index="compilePath(child.path)"@click="clickEvent(child)"v-if="!child.hidden"><iv-if="child.meta"class="iconfont":class="child.meta.iconName"></i><spanslot="title">{{child.name}}</span></el-menu-item></template><script>importpathfrom'path'exportdefault{props:{child:{type:Object},basePath:{type:String}},methods:{compilePath(childpath){returnpath.resolve(this.basePath,childpath)},clickEvent(child){constpath=this.compilePath(child.path)this.$router.push(path)}}}</script>
//sidebarItem.vue<template><el-submenuv-if="(item.children&&hasName(item))&&!item.hidden":index="item.path"><templateslot="title"><iv-if="item.meta"class="iconfont":class="item.meta.iconName"></i><spanslot="title">{{item.name}}</span></template><menu-itemv-for="childinitem.children":key="compilePath(item.path,child.path)":child="child":basePath="item.path"/></el-submenu><menu-item:child="item.children[0]"v-else-if="item.children&&!item.hidden":basePath="item.path"/></template><script>importpathfrom'path'importMenuItemfrom'./item.vue'exportdefault{props:{item:{type:Object}},components:{MenuItem},methods:{compilePath(itempath,childpath){returnpath.resolve(itempath,childpath)},hasName(item){returnitem.name?true:false}}}</script>

这样,我们的整个需求就完成了,然后将 sidebar 组件正常引入,加入自己的样式,就可以了

最后的最后,代码未经测试,有任何问题请私信或评论,谢谢。

作者:晴天同学


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:/Vue/816.html