主要是控制某些路由不用渲染成菜单,比如login 404 401等路由

默认hidden就是false 显示在菜单
image.png
image.png

菜单不显示 documentation hidden: true
image.png
效果图
image.png

2-1 SidebarItem组件修改

主要是在渲染菜单项前 根据route.meta.hidden属性进行筛选,将hidden为true 的筛选出去 不进行菜单渲染 image.png

  1. <template>
  2. <div
  3. v-if="!item.meta || !item.meta.hidden"
  4. class="sidebar-item-container"
  5. >
  6. <!-- 只渲染一个路由 并且路由只有一个子路由时直接渲染这个子路由 -->
  7. <template
  8. v-if="theOnlyOneChildRoute && (!theOnlyOneChildRoute.children || theOnlyOneChildRoute.noShowingChildren)"
  9. >
  10. <sidebar-item-link
  11. v-if="theOnlyOneChildRoute.meta"
  12. :to="resolvePath(theOnlyOneChildRoute.path)"
  13. >
  14. <el-menu-item
  15. :index="resolvePath(theOnlyOneChildRoute.path)"
  16. >
  17. <svg-icon
  18. v-if="icon"
  19. class="menu-icon"
  20. :icon-class="icon"
  21. ></svg-icon>
  22. <template #title>
  23. <span>{{ theOnlyOneChildRoute.meta.title }}</span>
  24. </template>
  25. </el-menu-item>
  26. </sidebar-item-link>
  27. </template>
  28. <!-- 有多个子路由时 -->
  29. <el-submenu
  30. v-else
  31. :index="resolvePath(item.path)"
  32. popper-append-to-body
  33. >
  34. <template #title>
  35. <svg-icon
  36. v-if="item.meta.icon"
  37. class="menu-icon"
  38. :icon-class="item.meta.icon"
  39. ></svg-icon>
  40. <span class="submenu-title">{{ item.meta.title }}</span>
  41. </template>
  42. <sidebar-item
  43. v-for="child in item.children"
  44. :key="child.path"
  45. :is-nest="true"
  46. :item="child"
  47. :base-path="resolvePath(child.path)"
  48. >
  49. </sidebar-item>
  50. </el-submenu>
  51. </div>
  52. </template>
  53. <script lang="ts">
  54. import path from 'path'
  55. import { defineComponent, PropType, computed, toRefs } from 'vue'
  56. import { RouteRecordRaw } from 'vue-router'
  57. import SidebarItemLink from './SidebarItemLink.vue'
  58. import { isExternal } from '@/utils/validate'
  59. export default defineComponent({
  60. name: 'SidebarItem',
  61. components: {
  62. SidebarItemLink
  63. },
  64. props: {
  65. item: {
  66. type: Object as PropType<RouteRecordRaw>,
  67. required: true
  68. },
  69. basePath: {
  70. type: String,
  71. required: true
  72. }
  73. },
  74. setup (props) {
  75. const { item } = toRefs(props)
  76. // 子路由数量
  77. const showingChildNumber = computed(() => {
  78. const children = (props.item.children || []).filter(child => {
  79. // hidden属性控制路由是否渲染成菜单 像login 401 404等路由都不需要渲染成菜案
  80. if (child.meta && child.meta.hidden) return false
  81. return true
  82. })
  83. return children.length
  84. })
  85. // 只有一个可渲染的子路由直接渲染这个子路由 (由于我们有的路由 layout布局组件是一级路由 二级路由才是我们要渲染成菜单)
  86. const theOnlyOneChildRoute = computed(() => {
  87. // 多个children
  88. if (showingChildNumber.value > 1) {
  89. return null
  90. }
  91. // 子路由只有一个时 并且做个hidden筛选 children是数组类型 所以循环下
  92. if (item.value.children) {
  93. for (const child of item.value.children) {
  94. // hidden属性控制路由是否渲染成菜单 像login 401 404等路由都不需要渲染成菜单
  95. if (!child.meta || !child.meta.hidden) {
  96. return child
  97. }
  98. }
  99. }
  100. // showingChildNumber === 0
  101. // 没有可渲染chiildren时 就渲染当前父路由item 可能children都是hidden或没有
  102. return {
  103. ...props.item,
  104. path: '', // resolvePath避免resolve拼接时 拼接重复
  105. noShowingChildren: true // 无可渲染chiildren
  106. }
  107. })
  108. // menu icon
  109. const icon = computed(() => {
  110. // 子路由 如果没有icon就用父路由的
  111. return theOnlyOneChildRoute.value?.meta?.icon || (props.item.meta && props.item.meta.icon)
  112. })
  113. // 拼接路径 父路径+子路径
  114. const resolvePath = (childPath: string) => {
  115. // 如果是带协议外链 直接返回
  116. if (isExternal(childPath)) {
  117. return childPath
  118. }
  119. // 如果不是外链 需要和basePath拼接
  120. return path.resolve(props.basePath, childPath)
  121. }
  122. return {
  123. theOnlyOneChildRoute,
  124. icon,
  125. resolvePath
  126. }
  127. }
  128. })
  129. </script>
  130. <style lang="scss">
  131. .sidebar-item-container {
  132. .menu-icon {
  133. margin-right: 16px;
  134. margin-left: 5px;
  135. vertical-align: middle;
  136. }
  137. }
  138. </style>

2-2 路由表里设置hidden

image.png

本节参考源码

https://gitee.com/brolly/vue3-element-admin/commit/e713893122b0ded1b56a783969a8e0405e61cdbc