多级侧边菜单(递归)

需要编写两个文件 aside-menu.vue 和 menu-item.vue

  1. menu-item.vue
html 复制代码
<script setup>
defineOptions({name: 'MenuItem'})
defineProps({menuList: Array})
</script>

<template>
  <template v-for="menu of menuList">
    <!-- 如果当前有子菜单,且子菜单只有一个时 -->
    <el-menu-item v-if="menu.children && menu.children.length === 1" :index="menu.path">
      <el-icon>
        <component :is="menu?.meta?.icon"></component>
      </el-icon>
      <template #title>
        <span>{{ menu.children[0]?.meta?.title }}</span>
      </template>
    </el-menu-item>
    <!-- 如果当前有子菜单,且子菜单大于一个时 -->
    <el-sub-menu
        v-if="menu.children && menu.children.length > 1"
        :index="menu.path"
    >
      <template #title>
        <el-icon>
          <component :is="menu?.meta?.icon"></component>
        </el-icon>
        <span>{{ menu?.meta?.title }}</span>
      </template>
      <!-- 调用自身  此处是重点-->
      <MenuItem :menuList="menu.children"></MenuItem>
    </el-sub-menu>
    <!-- 如果没有子菜单,则显示当前内容 -->
    <el-menu-item v-if="!menu.children || menu.children.length===0" :index="menu.path">
      <el-icon>
        <component :is="menu?.meta?.icon"></component>
      </el-icon>
      <template #title>
        <span>{{ menu?.meta?.title }}</span>
      </template>
    </el-menu-item>
  </template>
</template>

<style lang="scss" scoped>

</style>
  1. aside-menu.vue (menuList在该组件中请求后端接口获取)
html 复制代码
<script setup>
import MenuItem from "./menu-item.vue";

defineProps({
  isCollapse: {
    type: Boolean,
    default: true
  }
})
// 菜单列表
let menuList =[
    {
        path: '/',
        name: 'Layout',
        redirect: '/home',
        component: '/views/layout/index',
        meta: {
            title: 'Layout',
            icon: 'HomeFilled',
            hidden: false
        },
        children: [
            {
                path: '/home',
                name: 'Home',
                component: '/views/home/index',
                meta: {
                    title: '首页',
                    icon: 'HomeFilled',
                    hidden: false
                }
            },
        ]
    },
    {
        path: '/sys',
        name: 'Sys',
        component: '/views/layout/index',
        meta: {
            title: '系统管理',
            icon: 'document',
            hidden: false
        },
        children: [
            {
                path: '/sys/user',
                name: 'User',
                component: '/views/sys/user/index',
                meta: {
                    title: '用户管理',
                    icon: 'document',
                    hidden: false
                }
            },
            {
                path: '/sys/role',
                name: 'Role',
                component: '/views/sys/role/index',
                meta: {
                    title: '角色管理',
                    icon: 'document',
                    hidden: false
                }
            },
        ]
    }
]

//通过递归 将 menuList 属性hidden为true的菜单及其子菜单过滤掉
function filterHiddenMenu(menuList) {
  return menuList.filter(menu => {
    if (menu.children) {
      menu.children = filterHiddenMenu(menu.children)
    }
    return !menu?.mata?.hidden
  })
}

menuList = filterHiddenMenu(menuList)
</script>

<template>
  <div>
    <el-menu :collapse="isCollapse" :collapse-transition="false">
      <MenuItem :menu-list="menuList"></MenuItem>
    </el-menu>
  </div>
</template>

<style lang="scss" scoped>
.el-menu {
  height: 100%;
  width: 100%;
}
</style>
  1. 使用我们编写的 aside-menu组件
html 复制代码
<script setup>
import {ref} from "vue";
import AsideMenu from "./aside-menu/index.vue";

// 是否折叠菜单,默认折叠
const isCollapse = ref(true)

</script>

<template>
    <AsideMenu :isCollapse="isCollapse"></AsideMenu>
</template>

<style scoped lang="scss">
</style>
相关推荐
Zha0Zhun8 分钟前
一个使用ViewBinding封装的Dialog
前端
兆子龙8 分钟前
从微信小程序 data-id 到 React 列表性能优化:少用闭包,多用 data-*
前端
滕青山9 分钟前
文本行过滤/筛选 在线工具核心JS实现
前端·javascript·vue.js
时光不负努力11 分钟前
编程常用模式集合
前端·javascript·typescript
时光不负努力12 分钟前
ts+vue3开发规范
vue.js·typescript
大雨还洅下15 分钟前
前端JS: 跨域解决
javascript
恋猫de小郭18 分钟前
Apple 的 ANE 被挖掘,AI 硬件公开,宣传的 38 TOPS 居然是"数字游戏"?
前端·人工智能·ios
小岛前端22 分钟前
Node.js 宣布重大调整,运行十年的规则要改了!
前端·node.js
OpenTiny社区23 分钟前
OpenTiny NEXT-SDK 重磅发布:四步把你的前端应用变成智能应用
前端·javascript·ai编程
梦想CAD控件39 分钟前
在线CAD开发包结构与功能说明
前端·javascript·vue.js