Vue3 Element-plus el-menu无限级菜单组件封装
对于element中提供给我们的el-menu组件最多可以实现三层嵌套,如果多一层数据只能自己通过变量去加一层,如果加了两层、三层这种往往是行不通的,所以只能进行封装

一、定义数据
MenuData.ts
export default [{id: "1",name: "第一级菜单",level: '1',child: [{id: "11",name: "第二级菜单",level: '1-1',child: [{id: "111",name: "第三级菜单",level: '1-1-1',child: [{id: "1111",name: "第四级菜单",level: '1-1-1-1',child: [{id: "11111",name: "第五级菜单",level: '1-1-1-1-1',child: []}]}]}]}]},{id: "2",name: "第一级同级菜单",level: '2',child: []}]
二、封装组件
封装思想:
1.对本身组件进行循环使用,如果有子集使用本身组件 把child数据传给自己
2.如果没有子集 使用 el-menu-item
以下代码对setup( )函数和setup语法糖分别做了实现
setup语法糖
<template><el-menu:default-active="defaultActive":unique-opened="true"class="el-menu-vertical-demo"><template v-for="item in menu"><!-- 如果有子集 --><template v-if="item.child && item.child.length > 0"><el-sub-menu:key="item.id":index="item.level":disabled="item.meta?.disabled":popper-append-to-body="false"><template #title><i :class="[item.meta?.icon]"></i><!-- 添加空格 表示下级--><span> {{ generateSpaces(item.level) }} </span><span slot="title"> {{ item.name }}</span></template><MenuTree:menu="item.child":defaultActive="defaultActive"@clickItem="clickItemHandle"/></el-sub-menu></template><!-- 如果没有子集 --><template v-else><el-menu-item:key="item.id":index="item.level":disabled="item.meta?.disabled":popper-append-to-body="false"@click="clickItemHandle(item)"><i :class="[item.meta?.icon]"></i><!-- 添加空格 表示下级--><span> {{ generateSpaces(item.level) }} </span><span slot="title">{{ item.name }}</span></el-menu-item></template></template></el-menu>
</template><script lang="ts" name="MenuTree" setup>
// 把下面代码变成setup语法糖的形式
import type { PropType } from "vue";
import type { MenuItem } from "@/types/lesson";
// type 为了方便写成这样 可以根据自己项目设定typedefineProps({menu: {type: Array as unknown as PropType<any[]>,required: true,default: () => [],},defaultActive: {type: String as unknown as PropType<string>,required: true,default: [],},
});const emit = defineEmits(["update-active-path", "clickItem"]);// 返回的空格字符串 用于显示菜单层级
const generateSpaces = (level: string) => {let str = "";level.split("") .filter((it) => it != "-") .forEach(() => {str += " ";});return str;
};// 点击当前菜单项
const clickItemHandle = (item: MenuItem) => {emit("clickItem", item);
};
</script><style scoped lang="less">
.el-menu {width: 288px;
}
</style>
setup函数
<template><el-menu :default-active="defaultActive" :unique-opened="true" class="el-menu-vertical-demo" ><template v-for="item in menu"><template v-if="item.child && item.child.length > 0"><el-sub-menu :key="item.id":index="item.level":disabled="item.meta?.disabled":popper-append-to-body="false"><template #title><i :class="[item.meta?.icon]"></i><!-- 添加空格 表示下级--><span> {{ generateSpaces(item.level) }} </span><span slot="title"> {{ item.name }}</span></template><MenuTree :menu="item.child" :defaultActive="defaultActive" @clickItem="clickItemHandle" /></el-sub-menu></template><template v-else><el-menu-item :key="item.id":index="item.level":disabled="item.meta?.disabled":popper-append-to-body="false"@click="clickItemHandle(item)"><i :class="[item.meta?.icon]"></i><!-- 添加空格 表示下级--><span> {{ generateSpaces(item.level) }} </span><span slot="title">{{ item.name }}</span></el-menu-item></template></template></el-menu>
</template><script lang="ts">
import { defineComponent, toRefs } from 'vue';
import type { PropType } from 'vue'
import type {MenuItem} from '@/types/lesson'
export default defineComponent({name: 'MenuTree',props: {menu: {type: Array as unknown as PropType<any[]>,required: true,default: () => [],},defaultActive: {type: String as unknown as PropType<string>,required: true,default: '',},},emits: ['update-active-path','clickItem'],setup(props, context) {const { menu, defaultActive } = toRefs(props);const generateSpaces = (level:string) => {let str = ''level.split('').filter(it=>it!='-').forEach(() => {str += ' '})return str}const clickItemHandle = (item:MenuItem) => {context.emit('clickItem', item)}return {clickItemHandle,menu,defaultActive,generateSpaces,}},
});
</script><style scoped lang="less">.el-menu {width: 288px;}
</style>
type就不补充了 可根据自己项目定义,可临时改成any
三、使用组件
<template><MenuTree:menu="menuList":defaultActive="defaultActive"@clickItem="handleMenuClick":update-click="handleMenuClick"/>
</template><script setup lang="ts">
import MenuTree from "./components/MenuTree.vue";
import type {MenuItem} from '@/types/lesson'
import menuData from './MenuData'const defaultActive = ref<string>(''); // "1-1-1-1" 默认选中的数据
const menuList = ref(menuData)const handleMenuClick = (item:MenuItem) => {console.log('父组件',item);
};
</script>
补充default-active变量,如果一开始想默认点开第一层的数据 就需要找规律啦
拿到所有的level,通过接口方式返给你 自己平铺拿到所有的level也好
例如数据格式:
let arr = [ "1-1","1-1-1","1-1-1-1","1-1-1-2","1-1-1-3","1-1-1-4","1-1-1-5","1-1-1-6","1-1-2","1-1-2-1"
]
想要的结果就是 最长且相同数字最多的元素 1-1-1-1
arr.sort((a,b)=> b.split('-').length - a.split('-').length)[0]
使用split防止有些字符串是10、11 两位数字的
相关文章:

Vue3 Element-plus el-menu无限级菜单组件封装
对于element中提供给我们的el-menu组件最多可以实现三层嵌套,如果多一层数据只能自己通过变量去加一层,如果加了两层、三层这种往往是行不通的,所以只能进行封装 效果图 一、定义数据 MenuData.ts export default [{id: "1",name…...

( “树” 之 BST) 669. 修剪二叉搜索树 ——【Leetcode每日一题】
二叉查找树(BST):根节点大于等于左子树所有节点,小于等于右子树所有节点。 二叉查找树中序遍历有序。 669. 修剪二叉搜索树 给你二叉搜索树的根节点 root ,同时给定最小边界low 和最大边界 high。通过修剪二叉搜索树&…...

【C语言】浅涉结构体(声明、定义、类型、定义及初始化、成员访问及传参)
简单不先于复杂,而是在复杂之后。 目录 1. 结构体的声明 1.1 结构体的基础知识 1.2 结构的声明 1.3 结构成员的类型 1.4 结构体变量的定义和初始化 2. 结构体成员的访问 3. 结构体传参 1. 结构体的声明 1.1 结构体的基础知识 结构是一些值的集合&…...

设计模式-结构型模式之装饰模式
3. 装饰模式 3.1. 模式动机 一般有两种方式可以实现给一个类或对象增加行为: 继承机制 使用继承机制是给现有类添加功能的一种有效途径,通过继承一个现有类可以使得子类在拥有自身方法的同时还拥有父类的方法。但是这种方法是静态的,用户不能…...

【Chatgpt4 教学】 NLP(自然语言处理)第九课 朴素贝叶斯分类器的工作原理 机器学习算法
我在起,点更新NLP自然语言处理》《王老师带我成为救世主》 为啥为它单独开章,因为它值得,它成功的让我断了一更,让我实践了自上而下找能够理解的知识点,然后自下而上的学习给自己的知识升级,将自己提升到能…...

基于html+css的图片展示17
准备项目 项目开发工具 Visual Studio Code 1.44.2 版本: 1.44.2 提交: ff915844119ce9485abfe8aa9076ec76b5300ddd 日期: 2020-04-16T16:36:23.138Z Electron: 7.1.11 Chrome: 78.0.3904.130 Node.js: 12.8.1 V8: 7.8.279.23-electron.0 OS: Windows_NT x64 10.0.19044 项目…...

Jupyter Notebook小知识
目录 1 快捷键1.1 常用快捷键1.2 魔法函数 2 常用快捷键2.1 模式切换2.2 命令模式快捷键2.3 编辑模式快捷键3 Matplotlib绘图 4 小技巧4.1 文件默认目录的查看以及更改4.2 更改主题颜色 5 其它5.1 python中 r, b, u, f 的含义5.2 f/format():格式化操作 6 常见问题6.1 查看模块…...

redis原理及进化之路
Redis 的主从复制经历了多次演进,本文将从最基本的原理和实现讲起,并层层递进,逐步呈现 Redis 主从复制的演进历史。大家将了解到 Redis 主从复制的原理,以及各个改进版本解决了什么问题,并最终看清 Redis 7.0 主从复制…...

ai智能写作助手-ai自动写作软件
为什么要用ai智能写作工具 在数字化时代,AI(人工智能)技术已经被广泛应用于各种领域,其中之一是写作。AI智能写作工具是利用自然语言处理技术和机器学习算法来生成高质量的文章、博客、新闻稿等。这些工具不仅提供了便捷、高效的…...

redis持久化
redis提供两种方式进行持久化,一种是RDB持久化(原理是将Reids在内存中的数据库记录定时dump到磁盘上的RDB持久化),另外一种是AOF持久化(原理是将Reids的操作日志以追加的方式写入文件)。那么这两种持久化方…...

Vue项目基于driverjs实现新用户导航
引导页就是当用户第一次或者手动进行触发的时候,提示给用户当前系统的模块介绍,比如哪里是退出,哪里是菜单等等相应的操作。 无论是开发 APP 还是 web 应用,新手引导都是一个很常见的需求,一般在这2个方面需要新手引导…...

自编码器简单介绍—使用PyTorch库实现一个简单的自编码器,并使用MNIST数据集进行训练和测试
文章目录 自编码器简单介绍什么是自编码器?自动编码器和卷积神经网络的区别?如何构建一个自编码器?如何训练自编码器?如何使用自编码器进行图像压缩?总结使用PyTorch构建简单的自动编码器第一步:导入库和数…...

redis单机最大并发量
redis单机最大并发量 布隆过滤器多级缓存客户端缓存应用层缓存Expires和Cache-Control的区别Nginx缓存管理 服务层缓存进程内缓存进程外缓存 缓存数据一致性问题的解决引入多级缓存设计的时刻 Redis的速度非常的快,单机的Redis就可以⽀撑 每秒十几万的并发,相对于MySQL来说,性…...

MTLAB绘图
这里写目录标题 一、图例1、散点图 二、绘图1、总体图形参数2、坐标、图框、网格图框去上右边框小刻度网格坐标范围和刻度控制旋转 坐标、刻度 3、图例图例位置和方向 Location和Orientation图例加标题 、分多列 4、文本 字、字体、字号5、线型 符号6、颜色栏 colorbar7、颜色8…...

自媒体必备素材库,免费、商用,赶紧马住~
自媒体经常需要用到各类素材,本期就给大家安利6个自媒体必备的素材网站,免费、付费、商用都有,建议收藏起来~ 1、菜鸟图库 https://www.sucai999.com/video.html?vNTYwNDUx 菜鸟图库可以找到设计、办公、图片、视频、音频等各种素材。视频素…...

ESP32设备驱动-BMP388气压传感器驱动
BMP388气压传感器驱动 文章目录 BMP388气压传感器驱动1、BMP388介绍2、硬件准备3、软件准备4、驱动实现1、BMP388介绍 BMP388 是一款非常小巧、低功耗和低噪声的 24 位绝对气压传感器。 它可以实现精确的高度跟踪,特别适合无人机应用。 BMP388 在 0-65C 之间的同类最佳 TCO,…...

攻防世界-Reversing-x64Elf-100
Reversing-x64Elf-100 18最佳Writeup由 yuchouxuan 提供 收藏 反馈 难度:1 方向:Reverse 题解数:15 解出人数:2460 题目来源: 题目描述: 暂无 note:undefined8 FUN_004006fd(long param_1){int local_2c;char *local_28 …...

C/C++每日一练(20230419)
目录 1. 插入区间 🌟🌟🌟 2. 单词拆分 🌟🌟 3. 不同路径 🌟🌟 🌟 每日一练刷题专栏 🌟 Golang每日一练 专栏 Python每日一练 专栏 C/C每日一练 专栏 Java每日…...
[自注意力神经网络]Mask Transfiner网络-论文解读
本文为CVPR2022的论文。国际惯例,先贴出原文和源码: 原论文地址https://arxiv.org/pdf/2111.13673.pdf源码地址https://github.com/SysCV/transfiner 一、概述 传统的Two-Stage网络,如Mask R-CNN虽然在实例分割上取得了较好的效果ÿ…...

漫画:是喜,还是悲?AI竟帮我们把Office破活干完了
图文原创:亲爱的数据 国产大模型烈火制造。阿里百度字节美团各科技大佬不等闲。 大模型嘛,重大工程,对我等“怀保小民”来说,只关心怎么用,不关心怎么造。 我来介绍一下自己,我是一个写稿男团组合的成员&am…...

ChatGPT的原理分析
1.前言 ChatGPT是一种基于自然语言处理和人工智能技术的聊天机器人,它的基础是由OpenAI研发的GPT模型,其中GPT是Generative Pre-trained Transformer的缩写。GPT模型的训练使用了海量的语料库,可以预测下一个单词、短语、句子或文本…...

在线免费把Markdown格式文件转换为PDF格式
用CSDN的MarkDown编辑器在线转换 CSDN的MarkDown编辑器说实话还是挺好用的。 导出PDF操作步骤,图文配合看: 在MD编辑模式下写好MarkDown文章或者直接把要转换的MarkDown贴进来; 使用预览模式,然后在预览文件上右键选择打印&…...

R7-5 列车厢调度
R7-5 列车厢调度 分数 25 全屏浏览题目 切换布局 作者 周强 单位 青岛大学 1 <--移动方向/3 \2 -->移动方向 大家或许在某些数据结构教材上见到过“列车厢调度问题”(当然没见过也不要紧)。今天,我们就来实际操作一下列车…...

English Learning - L2 第 16 次小组纠音 弱读和语调 2023.4.22 周六
English Learning - L2 第 16 次小组纠音 弱读和语调 2023.4.22 周六 共性问题help /help/ 中的 e 和 lsorry /ˈsɒri/ 中的 ɒ 和 ilook out /lʊk aʊt/ 中的 ɒ 和 aʊdont /dəʊnt/ 中的 əʊemergency /ɪˈmɜːʤənsɪ/ 中的 ɜːname /neɪm/ 中的 eɪright /raɪt/…...

( “树” 之 前中后序遍历) 145. 二叉树的后序遍历 ——【Leetcode每日一题】
基础概念:前中后序遍历 1/ \2 3/ \ \ 4 5 6层次遍历顺序:[1 2 3 4 5 6]前序遍历顺序:[1 2 4 5 3 6]中序遍历顺序:[4 2 5 1 3 6]后序遍历顺序:[4 5 2 6 3 1] 层次遍历使用 BFS 实现,利用的就是 BFS…...

NPOI與Crystal report 13.0關於ICSharpCode.SharpZipLib控件版本衝突的解決方法
公司原來的系統用了Crystal report 13.0,它關聯使用ICSharpCode.SharpZipLib.dll (壓縮控件)的版本為0.85.1.271;後來因需要新增加 NPOI2.3控件,它關聯使用了ICSharpCode.SharpZipLib.dll 的版本為 高版本0.86…...

Sass @extend 与 继承
Sass extend 与 继承 extend 指令告诉 Sass 一个选择器的样式从另一选择器继承。 如果一个样式与另外一个样式几乎相同,只有少量的区别,则使用 extend 就显得很有用。 以下 Sass 实例中,我们创建了一个基本的按钮样式 .button-basic&#…...

权限控制导入到项目中
在项目中应用 进行认证和授权需要前面课程中提到的权限模型涉及的7张表支撑,因为用户信息、权限信息、菜单信息、角色信息、关联信息等都保存在这7张表中,也就是这些表中的数据是进行认证和授权的依据。所以在真正进行认证和授权之前需要对这些数据进行…...

CVPR2020:训练多视图三维点云配准
CVPR2020:训练多视图三维点云配准 Learning Multiview 3D Point Cloud Registration 源代码和预训练模型:https://github.com/zgojcic/3D_multiview_reg 论文地址: https://openaccess.thecvf.com/content_CVPR_2020/papers/Gojcic_Learn…...

string容器及其简单使用
string容器 概述声明和初始化获取字符串长度字符串拼接字符串比较字符串插入和删除字符串转换 概述 string是C中的一个标准库容器,用于处理字符串。它提供了一系列的操作函数,使得我们可以像处理其他容器一样方便地处理字符串。下面是string容器的详细介…...