经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » JS/JS库/框架 » JavaScript » 查看文章
使用vue-element-admin框架从后端动态获取菜单
来源:cnblogs  作者:#Empty  时间:2021/5/6 17:56:36  对本文有异议

1、前言

? vue-element-admin是一个纯前端的框架,左侧菜单是根据路由生成的。实际开发中经常需要根据当前登陆人员的信息从后端获取菜单进行展示,本文将详细介绍如何实现该功能。

2、详解

? 整体思路为:登陆 > 成功后根据用户信息获取菜单 > 根据菜单生成路由信息

2.1、新增asyncRoutes路由

? 在vue-router路径src\router\index.js中新增asyncRoutes数组,用来存放后端获取的菜单对应的路由信息。

  1. export const asyncRoutes = [
  2. { path: '*', redirect: '/404', hidden: true }
  3. ]

image-20210428151858065

constantRoutes和asyncRoutes的区别

constantRoutes:不需要动态判断权限的路由,如登录页、404等通用页面。

asyncRoutes:需求动态判断权限并通过addRoutes动态添加的页面

2.2、新建permission.js文件

? 在vuex路径src\store\modules\permission.js下新建permission.js文件,该操作为最重要的一步,主要是从后端查询菜单并生成路由。

  1. import { asyncRoutes, constantRoutes } from '@/router'
  2. import { fetchUserMenuList } from '@/api/user'
  3. import Layout from '@/layout'
  4. /**
  5. * 静态路由懒加载
  6. * @param view 格式必须为 xxx/xxx 开头不要加斜杠
  7. * @returns
  8. */
  9. export const loadView = (view) => {
  10. return (resolve) => require([`@/views/${view}.vue`], resolve)
  11. }
  12. /**
  13. * 把从后端查询的菜单数据拼装成路由格式的数据
  14. * @param routes
  15. * @param data 后端返回的菜单数据
  16. */
  17. export function generaMenu(routes, data) {
  18. data.forEach(item => {
  19. const menu = {
  20. path: item.url,
  21. component: item.component === '#' ? Layout : loadView(item.component),
  22. hidden: item.status === 0, // 状态为0的隐藏
  23. redirect: item.redirect,
  24. children: [],
  25. name: item.code,
  26. meta: item.meta
  27. }
  28. if (item.children) {
  29. generaMenu(menu.children, item.children)
  30. }
  31. routes.push(menu)
  32. })
  33. return routes
  34. }
  35. const state = {
  36. routes: [],
  37. addRoutes: []
  38. }
  39. const mutations = {
  40. SET_ROUTES: (state, routes) => {
  41. state.addRoutes = routes
  42. // 拼接静态路由和动态路由
  43. state.routes = constantRoutes.concat(routes)
  44. }
  45. }
  46. const actions = {
  47. generateRoutes({ commit }, token) {
  48. return new Promise(resolve => {
  49. // 通过token从后端获取用户菜单,并加入全局状态
  50. fetchUserMenuList(token).then(res => {
  51. const menuData = Object.assign([], res.data)
  52. const tempAsyncRoutes = Object.assign([], asyncRoutes)
  53. const accessedRoutes = generaMenu(tempAsyncRoutes, menuData)
  54. commit('SET_ROUTES', accessedRoutes)
  55. resolve(accessedRoutes)
  56. }).catch(error => {
  57. console.log(error)
  58. })
  59. })
  60. }
  61. }
  62. export default {
  63. namespaced: true,
  64. state,
  65. mutations,
  66. actions
  67. }

2.3、在vuex中注册permission模块

? 如果使用的是vue-element-admin请跳过此步,因为它在src\store\index.js中自动注册了src\store\modules下的所有模块。如果你使用的是vue-element-template,可以参考admin,将index.js文件改造一下,也可以手动import一下。

  1. import Vue from 'vue'
  2. import Vuex from 'vuex'
  3. import getters from './getters'
  4. Vue.use(Vuex)
  5. // https://webpack.js.org/guides/dependency-management/#requirecontext
  6. const modulesFiles = require.context('./modules', true, /\.js$/)
  7. // you do not need `import app from './modules/app'`
  8. // it will auto require all vuex module from modules file
  9. const modules = modulesFiles.keys().reduce((modules, modulePath) => {
  10. // set './app.js' => 'app'
  11. const moduleName = modulePath.replace(/^\.\/(.*)\.\w+$/, '$1')
  12. const value = modulesFiles(modulePath)
  13. modules[moduleName] = value.default
  14. return modules
  15. }, {})
  16. const store = new Vuex.Store({
  17. modules,
  18. getters
  19. })
  20. export default store

2.4、在getters中增加路由状态

? 在vuex路径src\store\getters.js添加menusRoutes状态

  1. menusRoutes: state => state.permission.routes

image-20210428151938637

2.5、修改菜单生成数据来源

? 在路径src\layout\components\Sidebar\index.vue修改routes数据来源,原来数据源是路由,改为从vuex中获取。

  1. routes() {
  2. // return this.$router.options.routes
  3. return this.$store.getters.menusRoutes
  4. },

image-20210428152509681

? 至此,从后端获取菜单数据到页面展示的逻辑已经完毕,下面开始在登陆后进行调用。

2.6、登陆后获取菜单

? 在vuex路径src\store\modules\user.js的login方法中,加入登陆成功通过token获取菜单生成路由逻辑。

  1. // 获取菜单,调用其他文件中actions时必须加 { root: true }
  2. dispatch('permission/generateRoutes', data, { root: true }).then((accessRoutes) => {
  3. router.addRoutes(accessRoutes)
  4. })

image-20210428153210137

2.7、解决刷新后页面空白

? 以上内容已经可以实现登陆后展示左侧菜单功能,但是会发现每次刷新页面后,页面都会变空白。这是因为在页面刷新时,会重新加载vue实例,vuex的store中的数据会被重新赋值,导致我们存在vuex中的路由信息被清空。

? 在src\permission.js中增加重新获取路由代码。

  1. const accessRoutes = await store.dispatch('permission/generateRoutes', store.getters.token)
  2. router.addRoutes(accessRoutes)
  3. next({ ...to, replace: true })

image-20210428155350723

3、总结

? 至此根据用户信息动态获取菜单内容已经全部完成。

转载请注明出处,原文链接:

https://www.cnblogs.com/gaozejie/p/14714616.html

原文链接:http://www.cnblogs.com/gaozejie/p/14714616.html

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号