el-menu根据多层树形结构递归遍历展示菜单栏

news/2024/9/25 4:22:13/

文章目录

  • 前提条件
  • 假设菜单等级只有两个等级
    • 结果如下所示
  • 但是如果菜单等级超过两个等级或者多个等级的话
    • App.vue
    • MenuItems.vue
    • 结果如下所示
  • 关于遍历时图标前的展示后续完善
  • 关于点击路由跳转参考element plus的官网即可

前提条件

package.json如下所示,这是一个Vite + Vue3 + TS的项目

{"name": "vue3-ts-vite-wen-zhang-ji-lu-xiang-mu","private": true,"version": "0.0.0","type": "module","scripts": {"dev": "vite","build": "vue-tsc && vite build","preview": "vite preview"},"dependencies": {"element-plus": "^2.4.2","vue": "^3.3.4"},"devDependencies": {"@vitejs/plugin-vue": "^4.2.3","sass": "^1.69.5","typescript": "^5.0.2","vite": "^4.4.5","vue-tsc": "^1.8.5"}
}

下面为了方便,直接在App.vue组件中,代码结构如下所示,就一纯净项目,然后直接在App.vue中写代码
在这里插入图片描述

假设菜单等级只有两个等级

如果菜单等级只有两个等级,那就没有必要使用到递归了,直接遍历,然后根据是否有children字段,判断是一级菜单还是二级菜单就可以了。具体代码如下所示:

<template><div style="width: 100%; height: 100%;"><div class="common-layout"><el-container><el-header>头部</el-header><el-container><!-- 侧边栏区域 --><el-aside width="200px"><el-menu default-active="2" class="el-menu-vertical-demo" @open="handleOpen" @close="handleClose"><template v-for="(item, index) in menuList" :key="index"><el-sub-menu :index="item.path" v-if="item.children && item.children.length"><template #title><el-icon><location /></el-icon><span>{{ item.name }}</span></template><el-menu-item v-for="child in item.children" :key="child.id" :index="child.path">{{ child.name }}</el-menu-item></el-sub-menu><el-menu-item v-else :index="item.path"><el-icon><setting /></el-icon><span>{{ item.name }}</span></el-menu-item></template></el-menu></el-aside><!-- 主题区域 --><el-main>这是主题区域</el-main></el-container></el-container></div></div>
</template><script setup lang="ts">javascript">
import { ref } from 'vue'
import { Location, Setting } from '@element-plus/icons-vue'interface MenuItem {id: number;name: string;path: string;icon?: string;component?: string;children?: MenuItem[];
}const menuList = ref<MenuItem[]>([{id: 1,name: '首页',path: '/',icon: 'location',component: 'home',children: []},{id: 2,name: '用户管理',path: '/user',icon: 'location',component: 'user',children: [{id: 3,name: '用户列表',path: 'list',icon: '',component: 'userList',children: []},{id: 5,name: '角色列表',path: 'roleList',icon: '',component: 'userList',children: []}]},{id: 6,name: '权限管理',path: '/permission',icon: 'setting',component: 'permission',children: [{id: 7,name: '权限列表',path: 'permissionList',icon: '',component: 'permissionList',}]}]
)const handleOpen = (key: string, keyPath: string[]) => {console.log(key, keyPath)
}
const handleClose = (key: string, keyPath: string[]) => {console.log(key, keyPath)
}</script><style scoped lang="scss">
.el-container {width: 100%;height: 100%;
}
</style>

结果如下所示

在这里插入图片描述

但是如果菜单等级超过两个等级或者多个等级的话

但是如果菜单等级超过两个等级或者多个等级的话,这时就可以使用到组件递归的方式进行了。目录结构如下所示:
在这里插入图片描述

App.vue

<template><div style="width: 100%; height: 100%;"><div class="common-layout"><el-container><el-header>头部</el-header><el-container><!-- 侧边栏区域 --><el-aside width="200px"><el-menu default-active="2" class="el-menu-vertical-demo" @open="handleOpen" @close="handleClose"><menu-items :items="menuList"></menu-items></el-menu></el-aside><!-- 主题区域 --><el-main>这是主题区域</el-main></el-container></el-container></div></div>
</template><script setup lang="ts">javascript">
import { ref } from 'vue'
import MenuItems from './components/MenuItems.vue'interface MenuItem {id: number;name: string;path: string;icon?: string;component?: string;children?: MenuItem[];
}const menuList = ref<MenuItem[]>([{id: 1,name: '首页',path: '/',icon: 'location',component: 'home',children: []},{id: 2,name: '用户管理',path: '/user',icon: 'location',component: 'user',children: [{id: 3,name: '用户列表',path: 'list',icon: '',component: 'userList',children: [{id: 4,name: '用户详情',path: 'userDetail',icon: '',component: 'userDetail',children: []}]},{id: 5,name: '角色列表',path: 'roleList',icon: '',component: 'userList',children: []}]},{id: 6,name: '权限管理',path: '/permission',icon: 'setting',component: 'permission',children: [{id: 7,name: '权限列表',path: 'permissionList',icon: '',component: 'permissionList',children: [{id: 8,name: '权限详情-1',path: 'permissionDetail',icon: '',component: 'permissionDetail',children: [{id: 9,name: '权限详情-2',path: 'permissionDetail2',icon: '',component: 'permissionDetail2',children: []}]}]}]}]
)const handleOpen = (key: string, keyPath: string[]) => {console.log(key, keyPath)
}
const handleClose = (key: string, keyPath: string[]) => {console.log(key, keyPath)
}</script><style scoped lang="scss">
.el-container {width: 100%;height: 100%;
}
</style>

MenuItems.vue

<template><template v-for="item in items" :key="item.id"><el-sub-menu v-if="item.children && item.children.length > 0" :index="item.path"><template #title><span>{{ item.name }}</span></template><!-- 递归遍历 --><menu-items :items="item.children" /></el-sub-menu><el-menu-item v-else :index="item.path"><span>{{ item.name }}</span></el-menu-item></template>
</template><script setup lang="ts">javascript">
interface MenuItem {id: number;name: string;path: string;icon?: string;component?: string;children?: MenuItem[];
}
defineProps<{items: MenuItem[];
}>()
</script>

结果如下所示

在这里插入图片描述
从图中可以看出,无论是一层,二层,三层,四层结构的树形数据,都可以在el-menu中展示。

关于遍历时图标前的展示后续完善

关于点击路由跳转参考element plus的官网即可


http://www.ppmy.cn/news/1499847.html

相关文章

redis高可用之主从复制、哨兵以及Cluster集群

目录 一、Redis主从复制 1&#xff09;主从复制的作用 2&#xff09;主从复制流程 3&#xff09;搭建Redis主从复制 1、部署redis服务器 2、修改Redis配置文件&#xff08;所有节点操作&#xff09; 3、验证主从复制结果 二、哨兵模式 1&#xff09;哨兵的作用 2&…

Rabbitmq从入门到精通

文章目录 1. RabbitMQ简介1.2 组件介绍1.1 消息队列的选择1.2 Docker 安装rabbitmq1.4 消息应答机制 2.1 交换机类型2.1 direct2.2 fanout2.3 topic&#xff1a;2.4header 3 RabbitMQ集群搭建3.1docker 搭建 rabbitmq集群 4 死信队列4.1 ttl消息过期&#xff1a;生产者添加延迟…

在CentOS 7上安装和使用PostgreSQL的方法

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到网站。 简介 关系数据库管理系统是许多网站和应用程序的关键组成部分。它们提供了一种结构化的方式来存储、组织和访问信息。 PostgreSQL&…

qt设置过滤器

1.创建事件过滤器类&#xff0c;在主窗口中安装事件过滤器 class PasteFilter : public QObject {Q_OBJECTpublic:PasteFilter(QObject *parent nullptr) : QObject(parent) {}protected:bool eventFilter(QObject *obj, QEvent *event) override {if (event->type() QEv…

上传文件传参 pc端vue的formData

formData let formData new FormData(); formData.append("file", blob, ref ".png"); //添加参数并且重新命名文件名称 if(ref.toString().indexOf(qrcode) > 0) formData.append(noStbg, true)//添加参数 uploadType(formData, sour…

通过mqtt.fx连接阿里云

通过mqtt.fx连接阿里云&#xff0c;需要完成以下步骤。请注意&#xff0c;以下步骤基于当前可用的信息和常见的操作流程&#xff0c;但实际操作时可能因阿里云平台的更新而有所变化。 一、阿里云平台配置 注册并登录阿里云账号&#xff1a; 访问阿里云官网&#xff08;aliyun…

告别手动打字!这个视频转文字方法,准确率高达98%

不知道大家是不是跟小小迅一样&#xff0c;平时喜欢看一些视频教程来学习ps等之类的技术。 不过视频学习有个痛点&#xff0c;就是不好整理总结。需要时不时暂停视频或者回放&#xff0c;记录下课程的重点等。如果遇到那种全程高能的知识类视频&#xff0c;可能整理笔记就需要…

将本地 Git 仓库连接到 GitHub 上的远程仓库

将本地 Git 仓库连接到 GitHub 上的远程仓库&#xff0c;并将本地的主要分支推送到远程仓库。 命令解释 git remote add origin https://github.com/xiaoqiuslam/ros_car.git&#xff1a; 这条命令将远程仓库添加为名为 origin 的远程库。 git branch -M main&#xff1a; 这…