当前位置:   article > 正文

2.vue3+ts+element-plus后台管理界面布局及动态侧边栏实现_vue3 后台管理菜单栏如何设计

vue3 后台管理菜单栏如何设计

1. 界面布局

  利用element-plus的布局组件实现:  <el-container> 整个布局容器,  <el-header> 顶部布局容器,  <el-aside> 侧边布局容器  <el-main> 主要布局容器。  采用组件化思想,将header和aside组件化,方便布局。

  1. <template>
  2. <div class="common-layout">
  3. <el-container>
  4. <CommonAside />
  5. <el-container>
  6. <el-header>
  7. <CommonHeader />
  8. </el-header>
  9. <el-main>
  10. <router-view />
  11. </el-main>
  12. </el-container>
  13. </el-container>
  14. </div>
  15. </template>
  16. <script lang="ts" setup>
  17. import CommonAside from '../components/CommonAside.vue'
  18. import CommonHeader from '../components/CommonHeader.vue'
  19. </script>
  20. color: var(--el-text-color-primary);
  21. }</style>

2.侧边栏布局及动态实现技术

侧边栏的布局,利用element-plus的el-menu组件实现。  el-menu组件实现第一级菜单,el-submenu实现第二级菜单。  el-menu-item实现菜单项,el-submenu-item实现二级菜单项。  el-menu-item-group实现菜单组,el-menu-item-group实现菜单组。

      所有菜单内容存储在数组menuData中,通过v-for指令动态渲染。通过noChildren过滤出没有子菜单的菜单数据也就是一级菜单数据。  通过hasChildren过滤出有子菜单的菜单数据也就是二级菜单数据。

  需要说明的是在vue3和elment-plus中: 
 1.el-menu-item和el-submenu-item组件的name属性值必须唯一,否则会报错。 
  index属性也必须唯一,否则后面现实菜单单击一项所有项全部响应。
 2.icon采用组件化设计,不同以前版本通过拼接字符串的方式调用组件(大多过去实现采用这种方法)。具体为:

   <component :is="item.icon" ></component>

   这块实现参考文章:https://blog.csdn.net/qq_40190624/article/details/125019530 说的较为详细。

ai推荐使用:<el-icon><icon-svg :icon-class="item.icon" /></el-icon>

   需要自定义的图标,可以到iconfont官网下载,然后放到static文件夹下,然后通过import引入。https://blog.csdn.net/qq_39246667/article/details/124347398 给出具体方法较为复杂.

  3.noChildren()方法最好存储成具体的变量,这样在代码中可以很方便的调用,而不用在v-for中直接调用函数。
  1. <template>
  2. <!-- <el-radio-group v-model="isCollapse" style="margin-bottom: 20px">
  3. <el-radio-button :label="false">expand</el-radio-button>
  4. <el-radio-button :label="true">collapse</el-radio-button>
  5. </el-radio-group> -->
  6. <el-menu default-active="2" class="el-menu-vertical-demo" :collapse="isCollapse" @open="handleOpen"
  7. @close="handleClose">
  8. <el-menu-item v-for="item in noChildren()" :key="item.name" :index="item.name">
  9. <component :is="item.icon" style="width: 18px;height: 18px;"></component>
  10. <template #title>{{item.label}}</template>
  11. </el-menu-item>
  12. <el-sub-menu v-for="item in hasChildren()" :key="item.name" :index="item.label">
  13. <template #title>
  14. <el-icon>
  15. <component :is="item.icon" style="width: 18px;height: 18px;"></component>
  16. </el-icon>
  17. <span>{{item.label}}</span>
  18. </template>
  19. <el-menu-item-group v-for="subItem in item.children" :key="subItem.name">
  20. <el-menu-item :index="subItem.name">{{subItem.label}}</el-menu-item>
  21. </el-menu-item-group>
  22. </el-sub-menu>
  23. </el-menu>
  24. </template>
  25. <script lang="ts" setup>
  26. import { ref } from 'vue'
  27. import {
  28. Document,
  29. Menu as IconMenu,
  30. Location,
  31. Setting,
  32. } from '@element-plus/icons-vue'
  33. // 声明一个变量isCollapse,值为false
  34. const isCollapse = ref(false)
  35. const menuData = [
  36. {
  37. path: "/",
  38. name: "home",
  39. label: "首页",
  40. icon: 'Menu',
  41. url: "Home/Home",
  42. },
  43. {
  44. path: "/mall",
  45. name: "mall",
  46. label: "商品管理",
  47. icon: "Document",
  48. url: "MallManage/MallManage",
  49. },
  50. {
  51. path: "/user",
  52. name: "user",
  53. label: "用户管理",
  54. icon: "Setting",
  55. url: "UserManage/UserManage",
  56. },
  57. {
  58. label: "其他",
  59. icon: "location",
  60. children: [
  61. {
  62. path: "/page1",
  63. name: "page1",
  64. label: "首页",
  65. icon: "Setting",
  66. url: "Other/PageOne",
  67. },
  68. {
  69. path: "/page2",
  70. name: "page2",
  71. label: "首页",
  72. icon: "Setting",
  73. url: "Other/PageTwo",
  74. },
  75. ],
  76. },
  77. ]
  78. // 声明一个函数handleOpen,参数为key和keyPath,用于接收参数
  79. const handleOpen = (key: string, keyPath: string[]) => {
  80. console.log(key, keyPath)
  81. }
  82. // 声明一个函数handleClose,参数为key和keyPath,用于接收参数
  83. const handleClose = (key: string, keyPath: string[]) => {
  84. console.log(key, keyPath)
  85. }
  86. const noChildren = () => { return menuData.filter((item) => !item.children) }
  87. // 过滤出没有子菜单的菜单数据
  88. const hasChildren = () => { return menuData.filter((item) => item.children) }
  89. // 过滤出有子菜单的菜单数据
  90. </script>
  91. <style>
  92. .el-menu-vertical-demo:not(.el-menu--collapse) {
  93. width: 200px;
  94. min-height: 400px;
  95. }
  96. </style>

注意:index 项目必须唯一 :index="item.label"  item.label选项各菜单都有且不同,子菜单项标题没有name,所以item.name报错。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/数据可视化灵魂/article/detail/62785?site
推荐阅读
相关标签
  

闽ICP备14008679号