一. 前言

本篇基于 有来商城 youlai-mall微服务项目,通过对vue-element-admin的权限菜单模块理解个性定制其后台接口,实现对vue-element-admin工程几乎不做改动的情况下,无缝接入后台接口实现动态权限菜单的加载。

在进行接下来的工作前,我们需要对原生的vue-element-admin项目改造,移除mock连通后台接口,具体可参考我这篇文章 vue-element-admin实战 | 第一篇: 移除mock接入后台,搭建有来商城youlai-mall前后端分离管理平台,如果在过程中有遇到问题,欢迎下方留言。

二. 前端调整

至于上文提到的对vue-element-admin几乎不做改动便可实现我们此篇文章的目的是不是我在扯,决定权给各位,我把对vue-element-admin项目改动的地方通过比对工具比对截图放上来。

先声明vue-element-admin此次改动的地方除了一个获取权限菜单的接口之外,剩余的改动全在 src/store/modules/permission.js 文件中。

看到了吗,可以说仅对vue-element-admin做两处改动,再加上对getRoutes调用后台接口返回的菜单数据的分析,就可以理解和实现动态权限菜单的加载了。

改动代码片段 + 注释说明

import {list as getRoutes} from '@/api/admin/menu'

import Layout from '@/layout'

generateRoutes({commit}, roles) {

return new Promise(resolve => {

// 请求后台数据替换src/router/index.js的asyncRoutes异步路由

getRoutes({mode: 3}).then(response => {

// filterAsyncRoutes方法作权限过滤和数据转换,roles为登录用户角色ID集合,如:[1,2]

let accessedRoutes = filterAsyncRoutes(response.data, roles)

commit('SET_ROUTES', accessedRoutes)

resolve(accessedRoutes)

})

})

}

// 递归权限过滤和数据转换

export function filterAsyncRoutes(routes, roles) {

const res = []

routes.forEach(route => {

const tmp = {...route}

if (hasPermission(roles, tmp)) {

const component = tmp.component

if (route.component) {

if (component == 'Layout') {

tmp.component = Layout

} else {

// 接口组件字符串转换成组件对象

tmp.component = (resolve) => require([`@/views/${component}`], resolve)

}

if (tmp.children) {

tmp.children = filterAsyncRoutes(tmp.children, roles)

}

}

res.push(tmp)

}

})

return res

}

三. 后端接口

1. 接口数据分析

接下来通过后台接口替换配置在src/router/index.js文件中asyncRoutes异步路由。

首先分析下异步路由的数据结构:

通过对上图异步路由的数据观察和了解,得出以下几点:

path在子路由中前面没有反斜杠'/'

根菜单的alwaysShow为true

component组件需通过import完成编译时导入,接口只能返回组件路径字符串,所以这里在接口请求完成后必须有一个组件路径字符串到组件对象的转换过程

meta的roles属性对应的是有该路由访问权限角色唯一标识的集合,这里我使用的是角色ID

2. 接口实现

完成以上的数据分析,接下来就是接口的具体实现了,有关SQL和完整代码请点击 有来商城 youlai-mall 拉取即可,以下仅仅贴出关键代码和分析。

SysMenuMapper

获取菜单列表和对应访问权限的角色ID的集合

SysMenuServiceImpl

将菜单转换成路由,递归生成父子结构树

SysMenuController

REST对外提供接口

3. 接口测试

完整返回数据,看看是不是很匹配asyncRoutes异步路由的数据格式了

{

"code": "00000",

"data": [{

"path": "/admin",

"component": "Layout",

"alwaysShow": true,

"name": "系统管理",

"meta": {

"title": "系统管理",

"icon": "documentation",

"roles": [2, 1]

},

"children": [{

"path": "user",

"component": "admin/user",

"alwaysShow": false,

"name": "用户管理",

"meta": {

"title": "用户管理",

"icon": "user",

"roles": [1]

}

}, {

"path": "role",

"component": "admin/role",

"alwaysShow": false,

"name": "角色管理",

"meta": {

"title": "角色管理",

"icon": "peoples",

"roles": [2, 1]

}

}, {

"path": "dept",

"component": "admin/dept",

"alwaysShow": false,

"name": "部门管理",

"meta": {

"title": "部门管理",

"icon": "tree",

"roles": [1, 2]

}

}, {

"path": "menu",

"component": "admin/menu",

"alwaysShow": false,

"name": "菜单管理",

"meta": {

"title": "菜单管理",

"icon": "tree-table",

"roles": [1, 2]

}

}, {

"path": "dict",

"component": "admin/dict",

"alwaysShow": false,

"name": "字典管理",

"meta": {

"title": "字典管理",

"icon": "education",

"roles": [1, 2]

}

}]

}],

"msg": "一切ok"

}

最后要做的就是将组件(component)路径字符串转换成组件对象即可,再次贴出在上文permission.js改造的代码:

if (component == 'Layout') {

tmp.component = Layout

} else {

// 接口组件字符串转换成组件对象

tmp.component = (resolve) => require([`@/views/${component}`], resolve)

}

有一点需要注意的是上面组件动态导入不能使用import,如下:

tmp.component = () => import(`@/views/${component}`)

不然会报以下错误

Error: Cannot find module '@/views/***'

原因是webpack不支持import动态导入了,但是之前确实是可以的,所以有些让人想不通,这里使用require动态导入组件即可。

4. 菜单权限测试

参看当前用户拥有的角色ID为2

用户管理要求只有角色ID为1才能有其访问权限

测试下用户登录控制台能否看到“用户管理”菜单

怎么样,只拥有角色ID为2的角色是看不到需要角色ID为1才能访问的“用户管理”菜单的,也就证明了我们成功通过接入后台接口实现了权限菜单的动态加载的目的。

四. 结语

其实有个问题值得去思考下的。为什么我们在从后台获取全部菜单列表的时候需要关联查询出有对应访问权限的角色ID的集合,而不是说动态传入当前登录用户的信息去查询该用户拥有的菜单集合呢?这其实是两种实现方式,区别在于第一种每个用户都要获取全部菜单数据,而第二种方式针对每个用户加载其拥有权限的菜单数据。单看的话第二种方式肯定优于第一种,但这里我们选用的是第一种加载全部菜单数据。如果你结合缓存去看的话自然就想的通了,所有用户共享缓存的同一份菜单数据,还是说缓存针对每个用户存放一份菜单缓存又或者用户每次都去请求数据库。后面计划把菜单数据存放到缓存Redis中然后做一个分析比较。

附完整代码:

写了这么多其实也是想给自己的项目打个广告,更希望对大家有所帮助,对于技术人来说少走弯路真的很重要,喜欢的朋友给个star,对我来说这份帮助更是自己继续下去的动力,所以谢谢了。有啥问题下方留言,或直接联系我(微信号:haoxianrui)。

vue 动态修改后端请求_vue-element-admin实战 | 第二篇: 最小改动接入后台实现根据权限动态加载菜单...相关推荐

  1. 基于vue-router的从后端动态加载菜单的实现

    基于vue-router的从后端动态加载菜单的实现 源码下载 前言 后端模拟加载菜单的例子实现 VueRouterController.java CorsConfig.java application ...

  2. 【看板】ajax动态获取后台传来json数据,加载到页面表格中

    ajax动态获取后台传来json数据,加载到页面表格中 摘要 1.WebApi 2.看板HTML 3.ajax获取后台传来的数据:在这里要注意声明提升,所以需要在for循环外var str1 = &q ...

  3. Django 权限管理-后台根据用户权限动态生成菜单

    Django权限管理 实现目标: 1.管理用户,添加角色,用户关联角色 2.添加权限.角色关联权限 3.添加动作.权限关联动作 4.添加菜单.权限关联菜单 实现动态生成用户权限菜单(可设置多级菜单嵌套 ...

  4. J版 OpenStack动态加载菜单图片详解

    首先,需要了解OpenStack Horizon动态加载.注册dashboard.PanelGroup.Panel的原理流程 一.这里大致说下与加载左侧菜单相关的几个文件 1. /usr/lib/py ...

  5. QML 地图修改插件源码(一)解决Map使用Open Street Map(OSM)无法加载在线地图的解决办法

    最近在使用Qml地图中发现,osm地图在线加载地图失败,通过查看osm插件源代码,找到了osm瓦片地图的源地址为:http://c.tile.openstreetmap.org/%z/%x/%y.pn ...

  6. vue 多个api请求_Vue+Django REST framework实战3.RESTful API和VUE目录结构

    内容提要: RESTful API和VUE基础概念. <Python前后端分离开发Vue+Django REST framework实战>作者bobby --学习来源 第四章 RESTfu ...

  7. vue怎么截取时间年月_Vue + Element 获取标准时间、时间戳进行转换与操作(年月日)...

    如图 获取标时间原生Date格式(Thu Aug 20 2020 14:55:18 GMT+0800 (中国标准时间)),并转换成 2020-08-20 模式 getTime (time) { var ...

  8. vue限制只能输入数字_vue+element 中 el-input框 限制只能输入数字及一位小数

    仅个人经验,希望能帮到有需要的人. 第一次写 就话不多说了直接上代码. // 只能输入数字且只有一位小数 proving(e) { // this.form.skus[e].Price 是input的 ...

  9. vue + element UI【实战】音乐播放器/语音条(内含音频的加载、控制,事件监听,信息获取,手机网页阴影的去除等技巧)

    相关技巧,详见注释 <template><!-- 音乐播放器 --><div class="container"><h2>{{ mu ...

最新文章

  1. 7.7. 其他证书工具
  2. 武鸣高中2021高考成绩查询,2019年广西两大重点高中成绩大比拼
  3. 快速看完整部教材,列出你不懂的 5 - 10 个问题
  4. web.xml.jsf_使用JSF 2.2功能来开发可滚动,可延迟加载的Ajax数据表
  5. 三维数组设置索引_python3三维数据结构 —— panel
  6. android 接口的调用方法参数类型转换,Android NDK开发之JNI基础
  7. 骁龙845_性能强大价格更吸引 超值骁龙845手机盘点
  8. apk反编译 Android apktool下载 dex2jar下载 jd-gui下载
  9. 腾讯云TDSQL TCP干货
  10. android4.4.3版本root,碉堡了!ROOT精灵支持Nexus 5等Android4.4.3机型ROOT
  11. 直接寻址、间接寻址、立即数寻址、寄存器寻址
  12. 联想全球裁员 MOTO移动业务被砍掉超过一半
  13. nginx方向代理域名访问
  14. 《Head First 设计模式》例子的C++实现(4 单件模式)
  15. 职业生涯手记——序章
  16. CAP 和 Zookeeper
  17. Codeforces Round #670 (Div. 2) C D E
  18. 《向上生长》读书摘记
  19. unity保存游戏对象到mysql_Unity实现游戏存档框架
  20. c语言字符串输入的陷阱

热门文章

  1. 从软件思想抽象出几条做事原则
  2. RSocket云原生架构下的另一种通信协议选择
  3. C++11 开启多线程
  4. 虚拟机Linux中判断用户输入的是 Yes 或 NO
  5. tinyxml 读取文本节点_TinyXml 读写XML文件
  6. python文本数据处理_从 App 描述介绍文字中发掘 Python 文本数据预处理实例
  7. ant design vue input change_vue 表单
  8. 为什么要打jar_生活在西北的兰州人过春节为什么要打太平鼓?
  9. winhttp get 实例_实例|CASS的绘制的航道断面,怎么多了两个边沟? 135
  10. 重磅!如何高效学习单目深度估计