Element Plus/vue3 无限级导航实现

在使用element plus 时,最初要使用的就是导航组件了,官网上看到的也就是写死的一级/二级导航,那么如何设计一个无限级且动态的导航呢?毋庸置疑,递归。废话不多说,直接看代码和效果:
代码:

8784c28b7e48b0055253bc69c854d4d9.png
目录结果

SidebarItem.vue

<template>
  <el-menu-item :index="item ? item.url : ''" v-if="!item || !item.children || item.children.length === 0">
    {{ item?.menuName }}
  </el-menu-item>

  <el-sub-menu :index="item ? item.id : ''" v-else>
    <template #title>
      <span class="tab">{{ item?.menuName }}</span>
    </template>

    <div v-for="(child, index) in item?.children" :key="index">
      <template v-if="child.children && child.children.length > 0">
        <sidebar-item :key="child.id" :item="child" />
      </template>
      <el-menu-item v-else :index="child.url">
        <span class="tab sub">{{ child.menuName }}</span>
      </el-menu-item>
    </div>
  </el-sub-menu>
</template>

<script lang="ts" setup>
import { PropType, toRefs } from 'vue';
import { MenuNode } from '../../../../model/menuNode';

const props = defineProps({
  collapse: {
    type: Boolean,
    default: true
  },
  item: {
    type: Object as PropType<MenuNode>,
  },
});

const { item } = toRefs(props);
</script>

<style lang="scss"></style>

Index.vue

<div class="nav">
      <el-scrollbar class="scrollbar">
        <el-menu class="menu" @open="handleOpen" @close="handleClose" mode="horizontal" router>
          <SidebarItem v-for="route in menuList" :key="route.id" :item="route"></SidebarItem>
        </el-menu>
      </el-scrollbar>
    </div>

测试数据:

export default [
    {
        'id': '001',
        'parentId': '0',
        'menuName': '首页',
        'url': '/dashboard',
        'sortNo': 1,
        'icon': 'Aim'
    },
    {
        'id': '002',
        'parentId': '0',
        'menuName': '表格',
        'url': '/charts',
        'sortNo': 4,
        'icon': 'ArrowDownBold'
    },
    {
        'id': '0021',
        'parentId': '002',
        'menuName': '树状图',
        'url': '/charts/charts1',
        'sortNo': 4,
        'icon': 'ArrowDownBold'
    },
    {
        'id': '0022',
        'parentId': '002',
        'menuName': '饼状图',
        'url': '/charts/charts2',
        'sortNo': 4,
        'icon': 'ArrowDownBold'
    },
    {
        'id': '003',
        'parentId': '0',
        'menuName': '测试四级1',
        'url': '/dashboard',
        'menuType': 1,
        'sortNo': 2,
        'icon': 'Aim'
    },
    {
        'id': '0031',
        'parentId': '003',
        'menuName': '测试四级2',
        'url': '/dashboard',
        'menuType': 1,
        'sortNo': 2,
        'icon': 'Aim'
    },
    {
        'id': '00311',
        'parentId': '0031',
        'menuName': '测试四级3',
        'url': '/dashboard',
        'menuType': 1,
        'sortNo': 2,
        'icon': 'Aim'
    },
    {
        'id': '003111',
        'parentId': '00311',
        'menuName': '测试四级4',
        'url': '/dashboard',
        'menuType': 1,
        'sortNo': 2,
        'icon': 'Aim'
    },
];

这里需要将数组转换成树形结构,也附上代码好了(纯手工输出,有bug还望见谅):

/*
 * @Author: zzh
 * @Date: 2022-03-01 14:39:16
 * @LastEditors: zzh
 * @LastEditTime: 2022-04-10 17:13:03
 * @Description: 数据转换帮助类
 * @FilePath: \zh-admin\src\utils\dataConvert.ts
 */

import { MenuNode } from '../model/menuNode';

// 由于菜单数据并非一颗树,而是多棵树组成的数据,顾当成由树组成的数组的处理
const convertMenuArrToTree = (array: Array<MenuNode>) => {
    const rootMenus = array.filter(x => x.parentId === '0');
    const childrenMenus = array.filter(x => x.parentId !== '0');
    for (let i = 0; i < rootMenus.length; i++) {
        if (childrenMenus.find(x => x.parentId === rootMenus[i].id)) {
            rootMenus[i].children = getRootMenuChild(rootMenus[i].id, childrenMenus);
        } else {
            rootMenus[i].children = [];
        }
    }
    return rootMenus;
};

const getRootMenuChild = (id: string, childrenMenus: Array<MenuNode>): Array<MenuNode> => {
    const menus = childrenMenus.filter(x => x.parentId === id);
    for (let i = 0; i < menus.length; i++) {
        if (childrenMenus.find(x => x.parentId === menus[i].id)) {
            menus[i].children = getRootMenuChild(menus[i].id, childrenMenus);
        } else {
            menus[i].children = [];
        }
    }
    return menus;
};



export {
    convertMenuArrToTree,
};

展示结果:

af47773eb6924169c74f22b03c8a2adb.png

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/633841.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

我在去哪儿薅到了5块钱火车票代金券,速薅

哈哈&#xff0c;亲爱的薅羊毛小伙伴们&#xff01; 刚刚在去哪儿大佬那儿发现了一个超级薅羊毛福利&#xff01;我只花了短短两分钟&#xff0c;就搞到了一张5块钱火车票代金券&#xff0c;简直是天上掉馅饼的节奏啊&#xff01; 话不多说&#xff0c;薅羊毛的姿势给你们摆好…

树的非递归遍历(层序)

层序是采用队列的方式来遍历的 就比如说上面这颗树 他层序的就是&#xff1a;1 24 356 void LevelOrder(BTNode* root) {Que q;QueueInit(&q);if (root){QueuePush(&q, root);}while (!QueueEmpty(&q)){BTNode* front QueueFront(&q);QueuePop(&q);print…

Docker Compose使用

Docker-Compose是什么 docker建议我们每一个容器中只运行一个服务,因为doker容器本身占用资源极少&#xff0c;所以最好是将每个服务单独分割开来&#xff0c;但是这样我们又面临了一个问题&#xff1a; 如果我需要同时部署好多个服务&#xff0c;难道要每个服务单独写Docker…

202473读书笔记|《但愿呼我的名为旅人:松尾芭蕉俳句300》——围炉夜话,身顿心安,愿每个人都能在爱里自由驰骋

202473读书笔记|《但愿呼我的名为旅人&#xff1a;松尾芭蕉俳句300》——围炉夜话&#xff0c;身顿心安&#xff0c;愿每个人都能在爱里自由驰骋 &#x1f60d;&#x1f60d;&#x1f929;&#x1f929; 译者序正文二正文三正文四正文五正文六正文七 《但愿呼我的名为旅人&…

网站笔记:huggingface——can you run it?

Can You Run It? LLM version - a Hugging Face Space by Vokturz 1 配置设置部分 Model Name就是需要测量的模型名称 GPU Vendor ——GPU供应商 Filter by RAM (按RAM过滤) 筛选出所有内存容量在选择范围之间的GPU GPU 下拉菜单选择具体的GPU型号 LoRa % trainable param…

MT3608B是一个恒定频率,6引脚SOT23电流模式升压转换器用于小型,低功耗应用的目的芯片IC

一般说明 该MT3608B是一个恒定频率&#xff0c;6引脚SOT23电流模式升压转换器用于小型&#xff0c;低功耗应用的目的。该MT3608B开关在1.2MHz&#xff0c;并允许使用微小&#xff0c;低成本的电容器和电感2毫米或更少的高度。内部软启动的结果在小浪涌电流和延长电池寿…

Linux网络——端口号理解与UDP协议

前言 在之前&#xff0c;我们学习了UDP通信与套接字编程&#xff0c;了解到需要使用端口号来表示网络中的数据需要传输到哪个进程&#xff0c;同时使用套接字的进行了UDP的通信。但当时在应用层&#xff0c;我们仅仅是浮于表面进行了初步的使用&#xff0c;今天我们来深入的理…

面试八股之MySQL篇1——慢查询定位篇

&#x1f308;hello&#xff0c;你好鸭&#xff0c;我是Ethan&#xff0c;一名不断学习的码农&#xff0c;很高兴你能来阅读。 ✔️目前博客主要更新Java系列、项目案例、计算机必学四件套等。 &#x1f3c3;人生之义&#xff0c;在于追求&#xff0c;不在成败&#xff0c;勤通…

卷积神经网络(CNN)详细介绍及其原理详解

卷积神经网络&#xff08;Convolutional Neural Networks&#xff0c;简称CNN&#xff09;是深度学习中非常重要的一类神经网络&#xff0c;主要用于图像识别、图像分类、物体检测等计算机视觉任务。本文将详细介绍卷积神经网络的基本概念、结构组成及其工作原理&#xff0c;并…

IIS网站搭建

1、添加网站 2、命名加上端口方便查看端口占用情况&#xff08;可有可无&#xff09; 3、导入sql文件&#xff0c;数据库打开——新建数据库——建好的数据库右键运行sql文件——打开路径网站下面的install文件下的sql——选中之后点开始——左侧页面的右键刷新就会显示。

2024最新 Jenkins + Docker 实战教程(四) - 编写自己的Springboot项目实现自动化部署

&#x1f604; 19年之后由于某些原因断更了三年&#xff0c;23年重新扬帆起航&#xff0c;推出更多优质博文&#xff0c;希望大家多多支持&#xff5e; &#x1f337; 古之立大事者&#xff0c;不惟有超世之才&#xff0c;亦必有坚忍不拔之志 &#x1f390; 个人CSND主页——Mi…

前端基础:1-2 面向对象 + Promise

面向对象 对象是什么&#xff1f;为什么要面向对象&#xff1f; 通过代码抽象&#xff0c;进而藐视某个种类物体的方式 特点&#xff1a;逻辑上迁移更加灵活、代码复用性更高、高度的模块化 对象的理解 对象是对于单个物体的简单抽象对象是容器&#xff0c;封装了属性 &am…

IP学习——ospf1

OSPF:开放式最短路径优先协议 无类别IGP协议&#xff1a;链路状态型。基于 LSA收敛&#xff0c;故更新量较大&#xff0c;为在中大型网络正常工作&#xff0c;需要进行结构化的部署---区域划分、ip地址规划 支持等开销负载均衡 组播更新 ---224.0.0.5 224.0.0.6 …

小程序properties默认值定义及父子组件的传值

因经常写vue&#xff0c;很久没写小程序&#xff0c;容易串频道&#xff0c;现记录一下小程序的组件用法、监听传入值及父子传值方式 首先小程序中传值是没有&#xff1a;(冒号)的&#xff0c;其次properties中定义默认值不需要写default 1.自定义组件中&#xff0c;首先json…

存储+调优:存储-IP-SAN

存储调优&#xff1a;存储-IP-SAN 数据一致性问题 硬盘&#xff08;本地&#xff0c;远程同步rsync&#xff09; 存储设备&#xff08;网络&#xff09; 网络存储 不同接口的磁盘 1.速率 2.支持连接更多设备 3.支持热拔插 存储设备什么互联 千…

iOS 17.5 release notes

文章目录 iOS 17.5 更新恢复了多年前删除的一些图片新增彩虹壁纸欧盟用户可直接从网站下载应用新增了追踪通知改进 Apple News图书应用"阅读目标"设计更新颜色匹配的播客小部件Web浏览器安全权限的访问下一代“Beats Pill”扬声器在iOS 17.5代码中得到确认店内Vision…

学硕都考11408的211院校!河北工业大学计算机考研考情分析!

河北工业大学&#xff08;Hebei University of Technology&#xff09;&#xff0c;简称河北工大&#xff0c;坐落于天津市&#xff0c;由河北省人民政府、天津市人民政府与中华人民共和国教育部共建&#xff0c; 隶属于河北省&#xff0c;是国家“双一流”建设高校、国家“211…

企业微信主体机构如何修改?

企业微信变更主体有什么作用&#xff1f; 做过企业运营的小伙伴都知道&#xff0c;很多时候经常会遇到现有的企业需要注销&#xff0c;切换成新的企业进行经营的情况&#xff0c;但是原来企业申请的企业微信上面却积累了很多客户&#xff0c;肯定不能直接丢弃&#xff0c;所以这…

OpenAI宫斗剧番外篇: “Ilya与Altman联手对抗微软大帝,扫除黑恶势力”,“余华”和“莫言”犀利点评

事情是这样的。 小编我是一个重度的智谱清言用户&#xff0c;最近智谱清言悄悄上线了一个“划词引用”功能后&#xff0c;我仿佛打开了新世界的大门。我甚至用这个小功能&#xff0c;玩出来了即将为你上映的《OpenAI宫斗剧番外篇》。 3.5研究测试&#xff1a;hujiaoai.cn 4研…

Stable Diffusion vs Midjunery的区别和选择

现在网上最多的关于AI绘画的工具莫过于stable diffusion&#xff08;sd&#xff09;和midjunery&#xff08;mj&#xff09;了&#xff0c;最近尝试了一番&#xff0c;稍作总结吧算是。我们对于工具的使用通常考虑的无非就是好不好用&#xff0c;效果如何&#xff0c;当然还有费…