Vue3 + Element Plus 多级嵌套菜单动态渲染

1 前言

1.1 功能

  • 动态渲染多级嵌套菜单
  • 点击菜单跳转页面
  • 子菜单高亮,对应父级菜单也高亮
  • 不同路由高亮同一菜单

1.2 源码

2 sub-menu 组件

<template>
  <el-sub-menu :index="menu.name" v-if="menu.childMenu">
    <template #title>
      <el-icon><Menu /></el-icon>
      <span>{
   
   { menu.chineseName }}</span>
    </template>
    <!-- 多级嵌套菜单渲染 -->
    <sub-menu :menu="menuItem" v-for="menuItem in menu.childMenu" :key="menuItem.name"></sub-menu>
  </el-sub-menu>
  <el-menu-item :index="menu.name" v-else>
    <el-icon><Menu /></el-icon>
    <template #title>{
   
   { menu.chineseName }}</template>
  </el-menu-item>
</template>

<script setup lang="ts">
interface Menu {
  name: string //菜单唯一标识,与路由名保持一致
  chineseName: string //菜单显示名称
  childMenu?: Menu[] | undefined //子菜单
}

defineProps<{
  menu: Menu
}>()
</script>

3 menu 组件

<template>
  <el-menu :default-active="defaultActive" router>
    <sub-menu :menu="menu" v-for="menu in menuList" :key="menu.name"></sub-menu>
  </el-menu>
</template>

<script setup lang="ts">
import { computed } from 'vue'
import { useRoute } from 'vue-router'
import SubMenu from './subMenu.vue'

// useRoute().meta?.parentMenu : 自定义路由点亮菜单,在路由的 meta 上配置 parentMenu 字段,值为父级菜单的 name 值
const defaultActive = computed(() => useRoute().meta?.parentMenu || useRoute().name)

const menuList = [
  {
    name: 'home',
    chineseName: '首页'
  },
  {
    name: 'literature',
    chineseName: '文学',
    childMenu: [
      {
        name: 'cartoon',
        chineseName: '动漫',
      },
      {
        name: 'essay',
        chineseName: '散文随笔',
        childMenu: [
          {
            name: 'youth_literature',
            chineseName: '青春文学',
          }
        ]
      },
      {
        name: 'suspenseful_reasoning',
        chineseName: '悬疑推理',
        childMenu: [
          {
            name: 'history',
            chineseName: '历史',
          },
          {
            name: 'noval',
            chineseName: '小说',
            childMenu: [
              {
                name: 'fiction',
                chineseName: '科幻',
              },
              {
                name: 'martial_arts',
                chineseName: '武侠',
              }
            ]
          }
        ]
      }
    ]
  },
  {
    name: 'psychology',
    chineseName: '心理学',
  }
]
</script>

<style lang="scss" scoped>
// 子菜单高亮,对应父级菜单也高亮
.el-menu ::v-deep(.el-sub-menu.is-active > .el-sub-menu__title) {
  color: var(--el-color-primary);
}
</style>

猜你喜欢

转载自blog.csdn.net/weixin_36757282/article/details/126609801