当前位置: 首页 > news >正文

vue 如何做一个动态的 BreadCrumb 组件,el-breadcrumb ElementUI

vue 如何做一个动态的 BreadCrumb 组件 el-breadcrumb ElementUI

在这里插入图片描述

一、ElementUI 中的 BreadCrumb 定义

elementUI 中的 Breadcrumb 组件是这样定义的

<template><el-breadcrumb separator="/"><el-breadcrumb-item :to="{ path: '/' }">主页</el-breadcrumb-item><el-breadcrumb-item>系统配置</el-breadcrumb-item><el-breadcrumb-item>基础配置</el-breadcrumb-item><el-breadcrumb-item>自动登录</el-breadcrumb-item></el-breadcrumb>
</template>

效果如图:
在这里插入图片描述

二、实现原理

我们需要实现的是,让它自己通过路由去填写这部分内容
原理是根据当前路由值,拆分成多个段,然后通过路由 path 去匹配对应的路由名称,再填入到上面的内容中即可。

比如:

1. 当前的路由值是 /system/normal-setup/auto-login

2. 通过拆分 / 生成一个数组

在这里插入图片描述

3. 依次匹配对应的路由名称

得到这个数组之后,依次去路由列表中匹配对应的路由名称

  • /system 系统配置
  • /system/normal-setup 基础配置
  • /system/normal-setup/auto-login 自动登录

4. 结果

这样就得到了一个 breadCrumb 数组,直接遍历这个数组,显示 BreadCrumb 即可

三、具体实现过程

知道了上面的实现原理,才会有具体的实现过程,这个过程还是有点麻烦的。

1. 处理路由数据

项目中用到的路由数据是这样的树形结构,路由数据的定义是这样的,里面的 children 可以嵌套任意层:

interface MenuEntity {id?: number | null,parent_id: number,name: string,icon?: string,type: EnumMenuType, // 1->目录 2->菜单 3->按钮 4->外链path: string,component?: string,visible: EnumMenuVisible, // 1->可见 2->隐藏 默认为1redirect: string,sort: number, // 默认为 20perm: string, // permissioncreated_at?: string,updated_at?: string,children?: MenuEntity[]
}

实际的数据是这样的:

{"name": "系统配置","id": 10,"parent_id": -1,"type": 1,"path": "/system","component": "","visible": 1,"redirect": "","perm": "","sort": 100,"icon": "Setting","created_at": "2024-02-26T14:55:12+08:00","updated_at": "2024-02-26T16:12:34+08:00","children": [{"name": "基础配置","id": 12,"parent_id": -1,"type": 1,"path": "/system/normal-setup","component": "","visible": 1,"redirect": "","perm": "","sort": 10,"icon": "CreditCard","created_at": "2024-02-26T15:20:15+08:00","updated_at": "2024-02-26T16:11:56+08:00","children": [{"name": "自动登录","id": 13,"parent_id": 12,"type": 2,"path": "/system/normal-setup/auto-login","component": "System/NormalSetup/AutoLoginSetup.vue","visible": 1,"redirect": "","perm": "","sort": 30,"icon": "User","created_at": "2024-02-26T15:24:18+08:00","updated_at": "2024-05-17T14:11:52+08:00","children": []},{"name": "系统更新","id": 28,"parent_id": 12,"type": 2,"path": "/system/normal-setup/system-update","component": "System/SystemUpdate.vue","visible": 1,"redirect": "","perm": "","sort": 50,"icon": "UploadFilled","created_at": "2024-02-26T16:19:49+08:00","updated_at": "2024-05-17T14:11:39+08:00","children": []},{"name": "申请厂家技术支持","id": 29,"parent_id": 12,"type": 2,"path": "/system/normal-setup/factory-help","component": "User/Space.vue","visible": 1,"redirect": "","perm": "","sort": 40,"icon": "SuitcaseLine","created_at": "2024-02-26T16:20:11+08:00","updated_at": "2024-03-27T09:04:20+08:00","children": []}]}]
}

为了好后续匹配 path 到路由名,需要将这个数据平化成一个数组,并构建一个 Map<path, RouteItem> 这样的一个 Map 数据,目的是当执行下面操作时,取到对应的路由数据

flatMenuPathNameMap.get('/system')// 最终取到这样的数据
{"name": "系统配置","id": 10,"parent_id": -1,"type": 1,"path": "/system","component": "","visible": 1,"redirect": "","perm": "","sort": 100,"icon": "Setting","created_at": "2024-02-26T14:55:12+08:00","updated_at": "2024-02-26T16:12:34+08:00",
}

平化树形数据、生成对应的 Map 数据结构:

/*** 菜单相关* 这里是单独放到了 pinia 中*/
export const useMenuStore = defineStore('menuStore', {state: () => ({menus: [] as Array<RouteRecordRaw>,flatMenuArray: [] as Array<MenuEntity>,flatMenuPathNameMap: new Map<string, string>()}),actions: {generateMenuArrayAndMap(){let menuString = localStorage.getItem('dataMenu')let menusCache = menuString ? JSON.parse(menuString) as Array<MenuEntity> : [] as Array<MenuEntity>let flatMenuArray = recursionMenuData(menusCache)this.flatMenuArray = flatMenuArraythis.flatMenuPathNameMap = new Map(flatMenuArray.map(item => [item.path, item.name]))// 递归方法,平化菜单数据function recursionMenuData(menuArray: Array<MenuEntity>){let tempArray: Array<MenuEntity> = []menuArray.forEach(item => {if (item.children && item.children.length > 0){tempArray = tempArray.concat(recursionMenuData(item.children))// 添加本身,并去除 children 属性delete item.childrentempArray.push(item)} else {tempArray.push(item)}})return tempArray}},}
})

使用的时候

import {useMenuStore, useProjectStore} from "./pinia";
const storeMenu = useMenuStore()
// 当执行下面的操作时就会补全  storeMenu.flatMenuArray 和  storeMenu.flatMenuPathNameMap
storeMenu.generateMenuArrayAndMap()

路由树的基础数据是这样的:

在这里插入图片描述

平化后的路由数组是这样的:
在这里插入图片描述

最终生成的 Map 数据是这样的:

在这里插入图片描述

2. 拆分当前路由 path,并匹配

比如当前路由是 /system/normal-setup/auto-login,把它通过 / 拆分之后就是这样的结果

import {useRoute} from "vue-router";
const route = useRoute()
let routeSectionArray = route.path.split('/').filter(item => item !== '')
// 这样拆分之后,前面会多出一个空白的 "" ,所以这里剔除了它

在这里插入图片描述
接下来要做的就是通过上面的 routerSectionArray 生成下面的几个路由组合,再去之前生成的 Map 中匹配对应的路由名即可

  • /system
  • /system/normal-setup
  • /system/normal-setup/auto-login

匹配之后就是这样的结果

  • /system 系统配置
  • /system/normal-setup 基础配置
  • /system/normal-setup/auto-login 自动登录

代码是这样的:

import {useRoute} from "vue-router";
import {onMounted, ref} from "vue";
import {useMenuStore} from "@/pinia";const storeMenu = useMenuStore()
const route = useRoute()const breadCrumbArray = ref<Array<{name: string, path: string}>>([])onMounted(()=>{let routeSectionArray = route.path.split('/').filter(item => item !== '')console.log(routeSectionArray)routeSectionArray.forEach((_, index) => {let path = `/${routeSectionArray.slice(0,index + 1).join('/')}`let pathName = storeMenu.flatMenuPathNameMap.get(path)console.log('---',pathName, path)if (pathName){breadCrumbArray.value.push({name: pathName, path: path})}})
})

四、搭配其它组件构建页面

弄好上面的 BreadCrumb 组件之后,就可以不用再管它内部的内容了,它会自动根据当前路由值生成对应的内容。
这样我们就可以放心的把它放到页面结构中了。

比如我的页面主要结构是这样的:

在这里插入图片描述

Toolerbar.vue

<template><div class="tool-bar"><div class="left"><Breadcrumb/><slot name="left"/></div><div class="center"><slot name="center"/></div><div class="right"><slot name="right"/></div></div>
</template><script setup lang="ts">import Breadcrumb from "@/layout/Breadcrumb.vue";
</script><style scoped lang="scss">
.tool-bar{padding: 0 20px;align-items: center;min-height: 50px;display: flex;flex-flow: row wrap;justify-content: space-between;.left{display: flex;flex-flow: row nowrap;justify-content: flex-start;align-items: center;flex-shrink: 0;}.center{display: flex;flex-flow: row nowrap;justify-content: flex-start;align-items: center;flex-grow: 1;flex-shrink: 0;}.right{display: flex;flex-flow: row nowrap;justify-content: flex-start;align-items: center;flex-shrink: 0;}
}
</style>

Breadcrumb.vue

<template><el-breadcrumb separator="/"><el-breadcrumb-item :to="{ path: '/' }">主页</el-breadcrumb-item><el-breadcrumb-itemv-for="item in breadCrumbArray":key="item">{{ item.name }}</el-breadcrumb-item></el-breadcrumb>
</template><script setup lang="ts">
import {useRoute} from "vue-router";
import {onMounted, ref} from "vue";
import {useMenuStore} from "@/pinia";const storeMenu = useMenuStore()
const route = useRoute()defineProps( {height: { // 高度type: Number,default: 100}
})const breadCrumbArray = ref<Array<{name: string, path: string}>>([])onMounted(()=>{let routeSectionArray = route.path.split('/').filter(item => item !== '')routeSectionArray.forEach((_, index) => {let path = `/${routeSectionArray.slice(0,index + 1).join('/')}`let pathName = storeMenu.flatMenuPathNameMap.get(path)console.log('---',pathName, path)if (pathName){breadCrumbArray.value.push({name: pathName, path: path})}})
})</script><style lang="scss" scoped>
@import "../assets/scss/plugin";</style>

实际页面中使用时这样:

<template><Container><Toolbar><template #left></template><template #center></template><template #right></template></Toolbar><Content></Content></Container>
<template>

五、结果

在这里插入图片描述

相关文章:

vue 如何做一个动态的 BreadCrumb 组件,el-breadcrumb ElementUI

vue 如何做一个动态的 BreadCrumb 组件 el-breadcrumb ElementUI 一、ElementUI 中的 BreadCrumb 定义 elementUI 中的 Breadcrumb 组件是这样定义的 <template><el-breadcrumb separator"/"><el-breadcrumb-item :to"{ path: / }">主…...

FFmpeg播放视频

VS2017+FFmpeg6.2.r113110+SDL2.30.5 1.下载 ShiftMediaProject/FFmpeg 2.下载SDL2 3.新建VC++控制台应用 3.配置include和lib 4.把FFmpeg和SDL的dll 复制到工程Debug目录下,并设置调试命令...

重叠区间的求和

#摘抄 GetGeneLength/src/GetGeneLength/GetGeneLength.py at main PoShine/GetGeneLength GitHub def main(): """ Extract gene length based on featureCount calculation gene nonredundant exon length method. """ # 引…...

java包装类 及其缓存

Java 包装类&#xff08;Wrapper Class&#xff09;是将基本数据类型转换为对象的方式&#xff0c;每个基本数据类型在 java.lang 包中都有一个相应的包装类&#xff1a; Boolean 对应基本类型 boolean Character 对应基本类型 char Integer 对应基本类型 int Float 对应基本…...

大龄程序员的出路在哪里?

对于许多资深程序员而言&#xff0c;年龄并非职业发展的桎梏&#xff0c;反而如同陈年的美酒&#xff0c;随着时间的流逝愈发醇厚。他们手握的是丰富的经验和不断进阶的技能&#xff0c;而这些都为他们打开了职业发展的无数扇大门。让我们一同探索这些令人心动的可能性吧&#…...

Unity不用脚本实现点击按钮让另外一个物体隐藏

1.首先在场景中创建一个按钮和一个其他随便什么东西 2.点击按钮中的这个加号 3.然后将刚刚你创建的物体拖到这里来 4.然后依次点击下面这些给按钮绑定事件 5.运行游戏并点击按钮&#xff0c;就会发现拖进来的物体消失了 总结&#xff1a;如果按钮的功能单一&#xff0c;可以使用…...

RAG技术-为自然语言处理注入新动力

引言&#xff1a; 在自然语言处理&#xff08;NLP&#xff09;的领域中&#xff0c;RAG&#xff08;Retrieval-Augmented Generation&#xff09;技术以其独特的方式&#xff0c;正在改变我们与机器的交互方式。RAG技术结合了大语言模型的强大能力&#xff0c;使得机器在理解和…...

Docker安装ELK(简易版)

1、下载ELK镜像&#xff1a;打开终端&#xff0c;并执行以下命令以下载Elasticsearch、Logstash和Kibana的Docker镜像。您也可以根据需要选择其他版本&#xff1a; docker pull docker.elastic.co/elasticsearch/elasticsearch:7.17.6 docker pull docker.elastic.co/logstash…...

WPF项目实战视频《一》(主要为WPF基础知识)

1.WPF布局&#xff1a; Grid&#xff0c;stackPanel&#xff0c;wrapPanel&#xff0c;DockPanel&#xff0c;UniformGrid Grid 按行列布局&#xff0c; Grid.ColumnDefinitions列&#xff0c;Grid.RowDefinitions行 Grid.Row“0” Grid.Column“0” stackPanel 默认从上往下排…...

iOS ------ ARC的工作原理

一&#xff0c;ARC的概念 ARC (Automatic Reference Counting&#xff0c;自动引用计数) 是苹果公司在其编程语言&#xff08;如 Objective-C 和 Swift&#xff09;中的内存管理机制。ARC 通过编译器插入的代码自动管理对象的内存生命周期&#xff0c;减少了手动内存管理的复杂…...

【React】JSX基础

一、简介 JSX是JavaScript XML的缩写&#xff0c;它是一种在JavaScript代码中编写类似HTML模板的结构的方法。JSX是React框架中构建用户界面&#xff08;UI&#xff09;的核心方式之一。 1.什么是JSX JSX允许开发者使用类似HTML的声明式模板来构建组件。它结合了HTML的直观性…...

1分钟带你了解苹果手机删除照片恢复全过程

在日常使用苹果手机时&#xff0c;我们可能会不小心删除掉一些重要的照片&#xff0c;这让人非常烦恼。那么苹果手机怎么恢复删除的照片&#xff1f;下面小编将会向大家介绍苹果手机恢复删除的照片的方法&#xff0c;帮助大家轻松找回你丢失的照片。 一、利用“最近删除”文件夹…...

Ruby爬虫技术:深度解析Zhihu网页结构

在互联网时代&#xff0c;数据的价值日益凸显&#xff0c;尤其是在社交媒体和问答平台如Zhihu&#xff08;知乎&#xff09;上&#xff0c;用户生成的内容蕴含着丰富的信息和洞察。本文将深入探讨如何使用Ruby爬虫技术来解析Zhihu的网页结构&#xff0c;并获取有价值的数据。 …...

python中的re模块--正则表达式

正则表达式&#xff0c;又称规则表达式。&#xff08;英语&#xff1a;Regular Expression&#xff0c;在代码中常简写为regex、regexp或RE&#xff09;&#xff0c;计算机科 学的一个概念。正则表达式通常被用来检索、替换那些符合某个模 式(规则)的文本 re模块作用 通过使用…...

sqlalchemy反射视图

sqlalchemy反射视图 一个名为my_view的视图,使用SQLAlchemy来操作这个视图 from sqlalchemy import create_engine, MetaData# 创建数据库连接 engine = create_engine(数据库连接字符串)# 创建一个MetaData对象 metadata = MetaData()# 反射视图 metadata.reflect(bind=eng…...

最新版康泰克完整版- Kontakt v7.10.5 for Win和Mac,支持m芯片和intel,有入库工具

一。世界最受欢迎的采样器的新篇章 Native Instruments Kontakt是采样器领域的标准&#xff0c;您将获得高质量的滤波器&#xff0c;在这里您将找到经典的模拟电路和最现代的滤波器。每一个都可以根据您的口味进行定制&#xff0c;并且由于它&#xff0c;您可以获得前所未有的声…...

spring boot(学习笔记第十三课)

spring boot(学习笔记第十三课) 传统后端开发模式和前后端分离模式的不同&#xff0c;Spring Security的logout&#xff0c;invalidateHttpSession不好用&#xff0c;bug&#xff1f; 学习内容&#xff1a; 传统后端开发模式 vs 前后端分离模式Spring Security的logout功能inv…...

聊聊不再兼容安卓的鸿蒙

鸿蒙NExt已经确定不再兼容安卓系统&#xff0c;这意味着鸿蒙系统在更新迭代上将会展现出更加迅猛的速度。不过&#xff0c;这样的变化也给开发者们带来了不小的挑战。如今&#xff0c;鸿蒙的开发主要推荐使用的是ArkTS&#xff0c;而不是我们熟悉的Java SDK。对于大量习惯于使用…...

创建一个矩形,当鼠标进入这个矩形的时候,这个矩形边线变色,且鼠标变成手型

1.概要 创建一个矩形&#xff0c;当鼠标进入这个矩形的时候&#xff0c;这个矩形边线变色&#xff0c;且鼠标变成手型 2.代码 #include <QApplication> #include "customRectWidget.h" /** qt 6.7版&#xff0c; 创建一个矩形&#xff0c;当鼠标进入这个矩形…...

AI自动生成PPT哪个软件好?高效制作PPT优选这4个

7.15初伏的到来&#xff0c;也宣告三伏天的酷热正式拉开序幕~在这个传统的节气里&#xff0c;人们以各种方式避暑纳凉&#xff0c;享受夏日的悠闲时光。 而除了传统的避暑活动&#xff0c;我们还可以用一种新颖的方式记录和分享这份夏日的清凉——那就是通过PPT的方式将这一传…...

使用docker在3台服务器上搭建基于redis 6.x的一主两从三台均是哨兵模式

一、环境及版本说明 如果服务器已经安装了docker,则忽略此步骤,如果没有安装,则可以按照一下方式安装: 1. 在线安装(有互联网环境): 请看我这篇文章 传送阵>> 点我查看 2. 离线安装(内网环境):请看我这篇文章 传送阵>> 点我查看 说明&#xff1a;假设每台服务器已…...

超短脉冲激光自聚焦效应

前言与目录 强激光引起自聚焦效应机理 超短脉冲激光在脆性材料内部加工时引起的自聚焦效应&#xff0c;这是一种非线性光学现象&#xff0c;主要涉及光学克尔效应和材料的非线性光学特性。 自聚焦效应可以产生局部的强光场&#xff0c;对材料产生非线性响应&#xff0c;可能…...

C++初阶-list的底层

目录 1.std::list实现的所有代码 2.list的简单介绍 2.1实现list的类 2.2_list_iterator的实现 2.2.1_list_iterator实现的原因和好处 2.2.2_list_iterator实现 2.3_list_node的实现 2.3.1. 避免递归的模板依赖 2.3.2. 内存布局一致性 2.3.3. 类型安全的替代方案 2.3.…...

Qt/C++开发监控GB28181系统/取流协议/同时支持udp/tcp被动/tcp主动

一、前言说明 在2011版本的gb28181协议中&#xff0c;拉取视频流只要求udp方式&#xff0c;从2016开始要求新增支持tcp被动和tcp主动两种方式&#xff0c;udp理论上会丢包的&#xff0c;所以实际使用过程可能会出现画面花屏的情况&#xff0c;而tcp肯定不丢包&#xff0c;起码…...

.Net框架,除了EF还有很多很多......

文章目录 1. 引言2. Dapper2.1 概述与设计原理2.2 核心功能与代码示例基本查询多映射查询存储过程调用 2.3 性能优化原理2.4 适用场景 3. NHibernate3.1 概述与架构设计3.2 映射配置示例Fluent映射XML映射 3.3 查询示例HQL查询Criteria APILINQ提供程序 3.4 高级特性3.5 适用场…...

Python爬虫(一):爬虫伪装

一、网站防爬机制概述 在当今互联网环境中&#xff0c;具有一定规模或盈利性质的网站几乎都实施了各种防爬措施。这些措施主要分为两大类&#xff1a; 身份验证机制&#xff1a;直接将未经授权的爬虫阻挡在外反爬技术体系&#xff1a;通过各种技术手段增加爬虫获取数据的难度…...

数据库分批入库

今天在工作中&#xff0c;遇到一个问题&#xff0c;就是分批查询的时候&#xff0c;由于批次过大导致出现了一些问题&#xff0c;一下是问题描述和解决方案&#xff1a; 示例&#xff1a; // 假设已有数据列表 dataList 和 PreparedStatement pstmt int batchSize 1000; // …...

【论文阅读28】-CNN-BiLSTM-Attention-(2024)

本文把滑坡位移序列拆开、筛优质因子&#xff0c;再用 CNN-BiLSTM-Attention 来动态预测每个子序列&#xff0c;最后重构出总位移&#xff0c;预测效果超越传统模型。 文章目录 1 引言2 方法2.1 位移时间序列加性模型2.2 变分模态分解 (VMD) 具体步骤2.3.1 样本熵&#xff08;S…...

让回归模型不再被异常值“带跑偏“,MSE和Cauchy损失函数在噪声数据环境下的实战对比

在机器学习的回归分析中&#xff0c;损失函数的选择对模型性能具有决定性影响。均方误差&#xff08;MSE&#xff09;作为经典的损失函数&#xff0c;在处理干净数据时表现优异&#xff0c;但在面对包含异常值的噪声数据时&#xff0c;其对大误差的二次惩罚机制往往导致模型参数…...

CVPR2025重磅突破:AnomalyAny框架实现单样本生成逼真异常数据,破解视觉检测瓶颈!

本文介绍了一种名为AnomalyAny的创新框架&#xff0c;该方法利用Stable Diffusion的强大生成能力&#xff0c;仅需单个正常样本和文本描述&#xff0c;即可生成逼真且多样化的异常样本&#xff0c;有效解决了视觉异常检测中异常样本稀缺的难题&#xff0c;为工业质检、医疗影像…...