经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » JS/JS库/框架 » Vue.js » 查看文章
el-menu动态加载路由的实现
来源:jb51  时间:2023/4/14 9:17:55  对本文有异议

先看需要实现的效果

这里有一级也有二级菜单,注意二级菜单的父目录(”选项设置“点击不会跳转,只是展开目录),然后点击去详情页,需要跳到一个隐藏的路由,不在菜单展示的路由

还有一点要注意,就是这里有两个router-view,整个页面是一个router-view,可以由LoginView和HomeView替换(当前看到的页面),而HomeView下又有一个router-view,需要用来展示部门,系统,超时,员工设置,不合格品列表和不合格品详情页。

以上的信息均需要在数据库的表中体现

先看看直接写在代码里需要哪些操作

  1. const routes = [
  2. {
  3. path: '',
  4. name: 'login',
  5. component: LoginView,
  6. }
  7. ,
  8. {
  9. component: HomeView,
  10. children: [
  11. {
  12. path: '/home',
  13. name: '不合格品列表',
  14. component: BelowStandard
  15. },
  16. {
  17. path: '/product/:id',
  18. name: '不合格品详情',
  19. component: BelowStandardDetail
  20. }
  21. ]
  22. },
  23. {
  24. component: HomeView,
  25. name: '选项设置',
  26. children: [
  27. {
  28. path: '/employee',
  29. name: '员工设置',
  30. component: EmployeeConfig,
  31. },
  32. {
  33. path: '/department',
  34. name: '部门设置',
  35. component: DepartmentConfig
  36. },
  37. {
  38. path: '/system',
  39. name: '系统设置',
  40. component: SystemConfig
  41. },
  42. {
  43. path: '/warn',
  44. name: '超时提醒',
  45. component: WarmConfig
  46. }
  47. ]
  48. },
  49. {
  50. component: HomeView,
  51. children: [
  52. {
  53. path: '/statistics',
  54. name: '统计',
  55. component: DailyStatistics
  56. }
  57. ]
  58. },
  59. {
  60. component: HomeView,
  61. children: [
  62. {
  63. path: '/log',
  64. name: '日志管理',
  65. component: LogManager
  66. }
  67. ]
  68. },
  69. ]

这是路由,当要动态从数据库加载时,就不能写在这

  1. <el-menu
  2. router
  3. active-text-color="#ffd04b"
  4. background-color="#000"
  5. class="el-menu-vertical-demo"
  6. :default-active="this.$route.path"
  7. text-color="#fff"
  8. @open=""
  9. @close=""
  10. >
  11. <el-menu-item index="/home">
  12. <template #title>
  13. 不合格品列表
  14. </template>
  15. </el-menu-item>
  16. <el-sub-menu index="/subMenuConfig">
  17. <template #title>
  18. 选项设置
  19. </template>
  20. <el-menu-item index="/department">部门设置</el-menu-item>
  21. <el-menu-item index="/system">系统设置</el-menu-item>
  22. <el-menu-item index="/warn">超时设置</el-menu-item>
  23. <el-menu-item index="/employee">员工设置</el-menu-item>
  24. </el-sub-menu>
  25. <el-menu-item index="/statistics">
  26. <span>统计</span>
  27. </el-menu-item>
  28. <el-menu-item index="/log">
  29. <span>日志管理</span>
  30. </el-menu-item>
  31. </el-menu>

这是el-menu开启了路由功能,所以能跳转路由,当动态加载的时候,这部分需要改造成v-for

数据库

说明:parent_id为0的即是一级目录,但是一级目录里一部分可以直接展示界面,一部分是展开二级目录,我这是以component字段为home/HomeView.vue来区分是展示二级目录。

现在开始写后端程序,返回菜单的json格式数据。

  1. List<Menu> menuList = menuMapper.getMenuByUserId(UserUtils.getLoginUser().getId());
  2. //根据ParentId分组
  3. Map<Integer, List<Menu>> map = menuList.stream().collect(Collectors.groupingBy(Menu::getParentId, TreeMap::new,Collectors.toList()));
  4. List<Menu> menus = map.get(0);//一级菜单
  5. menus.forEach(menu->{//给有二级菜单的目录设置children属性
  6. List<Menu> children = map.get(menu.getId());
  7. menu.setChildren(children);
  8. });
  9. return menus;

从数据库查询到的数据格式如图,然后分一级二级菜单处理后,再返回前端

  1. [
  2. {
  3. "name": "不合格品列表",
  4. "path": "/home",
  5. "component": "product/BelowStandard.vue",
  6. "orderNum": 1,
  7. "parentId": 0,
  8. "isHidden": false,
  9. "children": null
  10. },
  11. {
  12. "name": "选项设置",
  13. "path": "/subMenuConfig",
  14. "component": "home/HomeView.vue",
  15. "orderNum": 2,
  16. "parentId": 0,
  17. "isHidden": false,
  18. "children": [
  19. {
  20. "name": "员工设置",
  21. "path": "/employee",
  22. "component": "config/EmployeeConfig.vue",
  23. "orderNum": 1,
  24. "parentId": 2,
  25. "isHidden": false,
  26. "children": null
  27. },
  28. {
  29. "name": "部门设置",
  30. "path": "/department",
  31. "component": "config/DepartmentConfig.vue",
  32. "orderNum": 2,
  33. "parentId": 2,
  34. "isHidden": false,
  35. "children": null
  36. },
  37. {
  38. "name": "系统设置",
  39. "path": "/system",
  40. "component": "config/SystemConfig.vue",
  41. "orderNum": 3,
  42. "parentId": 2,
  43. "isHidden": false,
  44. "children": null
  45. },
  46. {
  47. "name": "超时提醒",
  48. "path": "/warn",
  49. "component": "config/WarmConfig.vue",
  50. "orderNum": 4,
  51. "parentId": 2,
  52. "isHidden": false,
  53. "children": null
  54. }
  55. ]
  56. },
  57. {
  58. "name": "统计",
  59. "path": "/statistics",
  60. "component": "statistics/DailyStatistics.vue",
  61. "orderNum": 3,
  62. "parentId": 0,
  63. "isHidden": false,
  64. "children": null
  65. },
  66. {
  67. "name": "日志管理",
  68. "path": "/log",
  69. "component": "log/LogManager.vue",
  70. "orderNum": 4,
  71. "parentId": 0,
  72. "isHidden": false,
  73. "children": null
  74. },
  75. {
  76. "name": "不合格品详情",
  77. "path": "/product/:id",
  78. "component": "product/BelowStandardDetail.vue",
  79. "orderNum": 5,
  80. "parentId": 0,
  81. "isHidden": true,
  82. "children": null
  83. }
  84. ]

前端得到数据之后进行处理,再添加到路由,过程中遇到一个问题,vue-router4版本去掉addRoutes换成addRoute带来的问题困扰我很久

用Vue3就必须用Router4.x版本,由于4.0去掉了addRoutes 所以只能用addRoute

现在是只能添加一个

  1. function routerPackag(routers:any) {
  2. if (routers) {
  3. routers.filter((itemRouter:any) => {
  4. if (itemRouter.component != "Layout") {
  5. router.addRoute('home',{ //home是父组件 add-route添加进父组件chilren里
  6. path: `${itemRouter.path}`,
  7. name: itemRouter.name,
  8. meta: {
  9. title: itemRouter.name,
  10. },
  11. component: () => import(`../views/${itemRouter.component}`),
  12. })
  13. }
  14. if (itemRouter.children && itemRouter.children.length) {
  15. routerPackag(itemRouter.children)
  16. }
  17. return true
  18. })
  19. }
  20. }

初始化路由:

  1. router.beforeEach((to, from, next) => {//配置路由守卫
  2. if(to.path==='/'){
  3. next()
  4. }else if(store.state.user.id){
  5. initMenus(router,store,next,to)
  6. }else{
  7. next({ path: '/',query: {redirect: to.path}});
  8. }
  9. });
  10.  
  11. export const initMenus = (router, store,next,to) => {//按F5刷新的话vuex里的会被清空,长度变为0
  12. if (store.state.menu !== null) {
  13. next()
  14. }else {
  15. axios.get("/menu").then(response => {
  16. if (response) {
  17. let responseData = response.data
  18. if (responseData.flag) {
  19. store.state.menu = responseData.data
  20. initRoute(router,store.state)
  21. next({...to,replace:true})//解决router4版本的第一次路由不匹配问题
  22. } else {
  23. this.$ElMessage.error('请求菜单失败')
  24. }
  25. }
  26. })
  27. }
  28. }
  29.  
  30. const initRoute = (router,state)=> {
  31. const loadView = view => {//这种引入方式控制台不会报警告
  32. // 路由懒加载
  33. return () => import(`@/views/${view}`)
  34. };
  35. const menus = state.menu
  36. const firstLevelMenu = {
  37. children: [],
  38. component: loadView('home/HomeView.vue')
  39. }
  40. menus.forEach(menu=>{
  41. menu.component = loadView(menu.component)
  42. if(menu.children === null || menu.children.length === 0){
  43. firstLevelMenu.children.push(menu)
  44. }else{
  45. menu.children.forEach(children=>{
  46. children.component = loadView(children.component)
  47. })
  48. router.addRoute(menu)
  49. }
  50. })
  51. router.addRoute(firstLevelMenu)
  52. }

完成这些配置之后,路由就能动态加载了,然后取出vuex中存储的menu生成el-menu

vuex中菜单大致如图

  1. <el-menu
  2. router
  3. active-text-color="#ffd04b"
  4. background-color="#000"
  5. class="el-menu-vertical-demo"
  6. :default-active="this.$route.path"
  7. text-color="#fff"
  8. @open=""
  9. @close=""
  10. >
  11. <template v-for="route of this.$store.state.menu">
  12. <template v-if="route.children === null || route.children.length === 0"><!--一级菜单-->
  13. <template v-if="!route.isHidden">
  14. <el-menu-item :index = "route.path">
  15. <span>{{route.name}}</span>
  16. </el-menu-item>
  17. </template>
  18. </template>
  19. <template v-else><!--二级菜单-->
  20. <template v-if="!route.isHidden">
  21. <el-sub-menu :index = "route.path">
  22. <template #title>
  23. <span>{{route.name}}</span>
  24. </template>
  25. <template v-for="children of route.children">
  26. <template v-if="!children.isHidden">
  27. <el-menu-item :index = "children.path">
  28. <span>{{children.name}}</span>
  29. </el-menu-item>
  30. </template>
  31. </template>
  32. </el-sub-menu>
  33. </template>
  34. </template>
  35. </template>
  36. </el-menu>

实现效果展示

到此这篇关于el-menu动态加载路由的实现的文章就介绍到这了,更多相关el-menu动态加载路由内容请搜索w3xue以前的文章或继续浏览下面的相关文章希望大家以后多多支持w3xue!

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

本站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号