【Vue3项目实战】vue3项目基于el-menu封装左侧菜单栏组件

文章目录

  • 概述
  • 一、先看效果
      • 1.1 静态效果
      • 1.2 动态效果
  • 二、核心思路
  • 三、全量代码
      • 3.1 文件目录结构
      • 3.2 /sidebar/index.vue 中
      • 3.3 /sidebar/sidebarItem.vue 中
      • 3.4 路由表结构
  • 四、代码讲解
  • 五、SVG组件
  • 六、系列文章友链
      • 1、[配置husky、stylelint、commitlint,实现git提交前代码校验](http://t.csdn.cn/226Xn)
      • 2、[配置@路径别名,实现@代替/src](http://t.csdn.cn/mMEwO)
      • 3、[配置 vue-router路由跳转,并完成路由模块化](http://t.csdn.cn/4r1ht)
      • 4、[配置vue-i18n中英文切换,完成国际化](http://t.csdn.cn/xyOaV)
      • 5、[配置滚动条样式](http://t.csdn.cn/cUkdA)
      • 6、[项目引入Element-plus,并配置按需自动导入](http://t.csdn.cn/mxdsS)
      • 7、[配置页面切换,路由跳转过渡动画](http://t.csdn.cn/LEKk6)
      • 8、[配置nprogress,实现路由加载进度条](http://t.csdn.cn/inFOa)

概述

做什么:封装通用左侧菜单栏组件
怎么做:使用 Element-Plus 组件库中的 el-menu组件进行二次封装
技术栈:Vue3 + Ts + Vite,且采用 setup 语法糖写法
准备工作:请各位自行引入Element-plus组件库,本文中有用到 svg组件,svg组件封装教程请看第五点

一、先看效果

1.1 静态效果

在这里插入图片描述

1.2 动态效果

请添加图片描述


二、核心思路

查看 Element-plus 组件库中的 el-menu 组件,不难发现,菜单栏大致可以分为两类,类是有子菜单的,一类是无子菜单的
所以我们将对这两类进行分情况设计,再结合递归,即可完成根据路由列表,动态渲染菜单栏

在这里插入图片描述


三、全量代码

3.1 文件目录结构

在这里插入图片描述

3.2 /sidebar/index.vue 中

<script lang="ts" setup>
// sidebarItem 项组件
import SideBarItem from './sidebarItem.vue';
import { useRouter } from 'vue-router';
// 拿到路由列表,过滤我们不想要的
const router = useRouter();
const routerList = router.getRoutes().filter((v) => v.meta && v.meta.isShow);
</script>
<template>
	<div class="sidebar">
		<!-- 项目名称及logo -->
		<div class="sidebar-logo flex-center">
			<svg-icon icon-class="logo" />
			<span>VitalityAdmin</span>
		</div>

		<!-- 导航菜单 -->
		<el-menu
			active-text-color="#fff"
			background-color="#001529"
			:default-active="$route.path"
			text-color="#999"
			:unique-opened="true"
			router>
			
            <!-- 引入子组件 -->
			<SideBarItem :routerList="routerList" />
		</el-menu>
		
		<!-- active-text-color:当前菜单项被选中时,字体的颜色 -->
		<!-- background-color:这个menu菜单的背景色 -->
		<!-- default-active:	当前激活菜单的 index -->
		<!-- text-color:菜单项字体颜色 -->
		<!-- unique-opened:unique-opened	是否只保持一个子菜单的展开 -->
		<!-- router:是否使用 vue-router 的模式,启用该模式会在激活导航时以 index 作为 path 进行路由跳转 -->
	</div>
</template>
<style lang="scss" scoped>
.sidebar {
	height: 100%;
	.sidebar-logo {
		height: 48px;
		background-color: #002140;
		color: #fff;
		font-weight: 700;
		line-height: 48px;
		text-align: center;
		font-size: 20px;
	}
	.el-menu {
		height: calc(100% - 48px);
		border-right: 0;
		overflow: auto;
	}
}
</style>

3.3 /sidebar/sidebarItem.vue 中

<script setup lang="ts">
import { RouteRecordRaw } from 'vue-router';
// 做类型限制,解决ts类型报错
type CustomRouteRecordRaw = RouteRecordRaw & {
	meta: {
		isShow?: boolean;
	};
};
const props = defineProps({
	// 拿到父组件传递过来的路由列表进行渲染
	routerList: {
		type: Array as () => CustomRouteRecordRaw[],
		required: true
	}
});
</script>
<template>
	<template v-for="item in props.routerList" :key="item.path">
		<!-- 当该菜单项有子菜单时 -->
		<el-sub-menu :index="item.path" v-if="item.children && item.children.length > 0">
			<template #title v-if="item.meta.icon">
				<!-- 菜单项图标,我此处用的是全局封装的 svg组件 -->
				<el-icon><svg-icon :icon-class="item.meta.icon" /></el-icon>
				<!-- 菜单项名称,在路由中定义好 -->
				<span>{{ item.meta.title }}</span>
			</template>
			<!-- 若路由中未定义菜单项icon,则仅展示名称--(我的仅一级菜单有图标) -->
			<template #title v-else>{{ item.meta.title }}</template>

			<!-- 递归遍历-自己调用自己(核心代码) -->
			<sidebarItem :routerList="( item.children as CustomRouteRecordRaw[])" />
		</el-sub-menu>

		<!-- 当前菜单项无子菜单 -->
		<el-menu-item :index="item.path" v-else>
			<!-- 与上面注释大致相同,不多做额外注释 -->
			<template v-if="item.meta.icon">
				<el-icon><svg-icon :icon-class="item.meta.icon" /></el-icon>
				<span>{{ item.meta.title }}</span>
			</template>
			<template v-else>
				{{ item.meta.title }}
			</template>
		</el-menu-item>
	</template>
</template>

<style scoped lang="scss">
.is-active {
	background: #409eff;
	font-weight: 700;
}

.el-menu-item {
	&:hover {
		color: #fff;
		font-weight: 700;
	}
}

.el-menu--collapse {
	.el-menu-item {
		justify-content: center;
	}
}

// 下列代码是用于兼容horizontal所写,酌情删或留
.el-menu--horizontal {
	.el-menu-item.is-active {
		background-color: transparent !important;
		border-bottom: 2px solid #409eff !important;

		.el-icon,
		span {
			color: #409eff !important;
		}
	}

	.el-sub-menu.is-active {
		.el-sub-menu__title {
			border: 0 !important;
		}

		.el-icon,
		span {
			color: #409eff !important;
		}
	}
}
</style>


3.4 路由表结构

isShow: true, // 控制当前项是否在菜单栏中渲染出来,比如你写了 login 页面的路由,但是并不希望 login在menu菜单中渲染出来,即可设为false
title: ‘首页’, // menu菜单项的名称,没啥好说的
icon: ‘menu-home’ // menu菜单项的图标,我此处是与封装好的 svg 组件结合使用的

export default [
	{
		path: '/layout',
		name: 'layoutIndex',
		component: () => import('@/layout/index.vue'),
		children: [
			{
				path: '/home',
				name: 'homeIndex',
				component: () => import('@/views/home/index.vue'),
				meta: {
					isShow: true, // 控制当前项是否在菜单栏中渲染出来,比如你写了 login 页面的路由,但是并不希望 login在menu菜单中渲染出来,即可设为false
					title: '首页', // menu菜单项的名称,没啥好说的
					icon: 'menu-home' // menu菜单项的图标,我此处是与封装好的 svg 组件结合使用的
				}
			},
			{
				path: '/echarts',
				name: 'echartIndex',
				// component: () => import('@/views/echarts/index.vue'),
				meta: {
					isShow: true,
					title: 'Echarts页',
					icon: 'menu-echarts'
				},
				children: [
					{
						path: '/echarts/barCharts',
						name: 'barCharts',
						component: () => import('@/views/echarts/barCharts.vue'),
						meta: {
							title: '柱状图'
						}
					},
					{
						path: '/echarts/pieCharts',
						name: 'pieCharts',
						component: () => import('@/views/echarts/pieCharts.vue'),
						meta: {
							title: '饼图'
						}
					}
				]
			},
			{
				path: '/package',
				name: 'packageIndex',
				component: () => import('@/views/package/index.vue'),
				meta: {
					isShow: true,
					title: '组件',
					icon: 'menu-package'
				}
			},
			{
				path: '/menu',
				name: 'menuIndex',
				redirect: '/menu/menu-1',
				meta: {
					isShow: true,
					title: '一级菜单',
					icon: 'menu-package'
				},
				children: [
					{
						path: '/menu/menu-1',
						name: 'menu-1',
						component: () => import('@/views/menu/menu1.vue'),
						meta: {
							title: '二级菜单-1'
						}
					},
					{
						path: '/menu/menu-2',
						name: 'menu-2',
						component: () => import('@/views/menu/menu2.vue'),
						meta: {
							title: '二级菜单-2'
						},
						children: [
							{
								path: '/menu/menu-2/children',
								name: 'menu3',
								component: () => import('@/views/menu/menu3.vue'),
								meta: {
									title: '三级菜单'
								}
							}
						]
					}
				]
			}
		]
	}
];


四、代码讲解

在这里插入图片描述

在这里插入图片描述


五、SVG组件

本文不展开讲解 svg组件 的封装与使用,有需要的朋友欢迎参考下面的 svg组件 封装教程

svg组件封装教程:http://t.csdn.cn/uYsSJ

六、系列文章友链

本系列文章记录了从零到一 🚀 搭建 Vue3+Ts+Vite 项目的全过程
包括但不限于项目配置、组件封装、过渡动画等 🚚
系列文章持续更新中~~👨🏻‍💻,有任何问题欢迎👏评论区留言
最后,希望本文都能对你有一点🤏🏽帮助,点赞收藏不迷路🍺

1、配置husky、stylelint、commitlint,实现git提交前代码校验

2、配置@路径别名,实现@代替/src

3、配置 vue-router路由跳转,并完成路由模块化

4、配置vue-i18n中英文切换,完成国际化

5、配置滚动条样式

6、项目引入Element-plus,并配置按需自动导入

7、配置页面切换,路由跳转过渡动画

8、配置nprogress,实现路由加载进度条

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

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

相关文章

HadoopWEB页面上传文件报错Couldn‘t upload the file course_info.txt

HadoopWEB页面上传文件报错Couldn’t upload the file course_info.txt 右键F2检查发现&#xff1a;文件上传PUT操作的IP地址是节点IP别名识别不到导致 解决方法&#xff1a;在WEB页面访问浏览器所在机器上面配置hosts映射地址(注意:配置的是浏览器访问的地址不是hadoop节点所在…

使用Golang实现一套流程可配置,适用于广告、推荐系统的业务性框架——组合应用

在《使用Golang实现一套流程可配置&#xff0c;适用于广告、推荐系统的业务性框架——简单应用》中&#xff0c;我们看到了各种组合Handler的组件&#xff0c;如HandlerGroup和Layer。这些组件下面的子模块又是不同组件&#xff0c;比如LayerCenter的子组件是Layer。如果此时我…

网络安全(黑客)自学的误区

一、自学网络安全学习的误区和陷阱 1.不要试图先成为一名程序员&#xff08;以编程为基础的学习&#xff09;再开始学习 我在之前的回答中&#xff0c;我都一再强调不要以编程为基础再开始学习网络安全&#xff0c;一般来说&#xff0c;学习编程不但学习周期长&#xff0c;而…

项目中使用非默认字体

项目场景&#xff1a; 由于开发需要&#xff0c;默认的字体不符合开发需求&#xff0c;有时候我们需要引入某种字体到项目中 解决方案&#xff1a; 首先需要下载或引入字体包 然后创建一个 index.css 文件用于声明引入字体名称 font-face {font-family: "YouSheBiao…

C语言多级指针

#include "stdio.h" #include <stdlib.h>int main() {int a 10;//*p int a int *pint* p &a;int** q &p;//int** q int *(*q) int *(q) a//int**q int*(*q) int*(&a) int*&a aint*** k &q;//分析&#xff1a;首先k是个变量&…

大模型系列|基于大模型复杂数据系统架构(二)

张俊林老师在 2023 WAIC AI 开发者论坛的演讲非常有概括性&#xff0c;这边沿着思路进行一定的整理。&#xff08;文章来源&#xff1a;WAIC 2023 | 张俊林&#xff1a;大语言模型带来的交互方式变革&#xff09; 文章目录 1 PlanningProgramming 模式的系统技术架构2 HuggingG…

【Linux】创建与删除用户

新增用户&#xff1a; adduser 用户名【添加用户】 passwd 用户名【设置用户密码】删除用户&#xff1a; userdel -r 用户名【删除用户】

【多模态】23、RO-ViT | 基于 Transformer 的开发词汇目标检测(CVPR2023)

文章目录 一、背景二、方法2.1 基础内容2.2 Region-aware Image-text Pretraining2.3 Open-vocabulary Detector Finetuning 三、效果3.1 细节3.2 开放词汇目标检测效果3.3 Image-text retrieval3.4 Transfer object detection3.5 消融实验 论文&#xff1a;Region-Aware Pretr…

如何解决电脑无声问题:排除故障的几种常见方法

大家好&#xff0c;今天我们来讨论一下处理电脑没有声音的故障。当你突然发现电脑静音无声时&#xff0c;需要逐步排除可能的问题&#xff0c;但总体而言&#xff0c;声音故障是相对容易解决的。接下来&#xff0c;我们将介绍一些排除电脑无声问题的方法。 第一步&#xff1a;…

使用 FastGPT 构建高质量 AI 知识库

作者&#xff1a;余金隆。FastGPT 项目作者&#xff0c;Sealos 项目前端负责人&#xff0c;前 Shopee 前端开发工程师 FastGPT 项目地址&#xff1a;https://github.com/labring/FastGPT/ 引言 自从去年 12 月 ChatGPT 发布以来&#xff0c;带动了一轮新的交互应用革命。尤其在…

安卓:BottomNavigationBar——底部导航栏控件

目录 一、BottomNavigationBar介绍 二、BottomNavigationBar的常用方法及其常用类 &#xff08;一&#xff09;、常用方法 1. 添加菜单项 2. 移除菜单项 3. 设置选中监听器 4. 设置当前选中项 5. 设置徽章 6. 样式和颜色定制 7. 动画效果 8. 隐藏底部导航栏。 9、设…

windows物理机 上安装centos ,ubuntu,等多个操作系统的要点

一、摘要 一般情况下&#xff0c;我们的笔记本或工作电脑都默认安装windows 分几个区&#xff0c;当下是win7 win8 win 10 win11 等&#xff0c;突然我们有需求需要安装个centos &#xff0c;后面我们应当怎么做&#xff0c;要点是什么&#xff1f;一定要根据网上的贴子一步步来…

【Golang 接口自动化00】为什么要用Golang做自动化?

目录 为什么使用Golang做自动化 最终想实现的效果 怎么做&#xff1f; 写在后面 资料获取方法 为什么使用Golang做自动化 顺应公司的趋势学习了Golang之后&#xff0c;因为没有太多时间和项目来实践&#xff0c;怕止步于此、步Java缺少练习遗忘殆尽的后尘&#xff0c;决定…

【iOS】json数据解析以及简单的网络数据请求

文章目录 前言一、json数据解析二、简单的网络数据请求三、实现访问API得到网络数据总结 前言 近期写完了暑假最后一个任务——天气预报&#xff0c;在里面用到了简单的网络数据请求以及json数据的解析&#xff0c;特此记录博客总结 一、json数据解析 JSON是一种轻量级的数据…

vulnhub靶机Empire_LupinOne

下载地址&#xff1a;https://www.vulnhub.com/entry/empire-lupinone,750/ 主机发现 arp-scan -l nmap --min-rate 10000 -p- 192.168.21.137 nmap -sV -sT -O -p22,80 192.168.21.137 nmap --scriptvuln -p22,80 192.168.21.137 先看一下网页 啥也没有 先看一下nmap扫出来的…

10.物联网操作系统之低功耗管理

一。低功耗管理概念及其应用 1.STM32低功耗设计详解 STM32的电源管理系统主要分为&#xff1a; 备份域 调压器供电电路 ADC电源电路 2.低功耗模式 1.运行模式 2.睡眠模式 3.停机模式 4.待机模式 &#xff08;1&#xff09;睡眠模式 在睡眠模式中&#xff0c;仅关闭了内核时钟&…

带你简单认识淘宝 API 接口,API接口适用场景和业务类型

淘宝 API 接口是为开发电商类应用程序而设计的一套完整的、跨浏览器、跨平台的接口规范。通过开放接口&#xff0c;开发者可以不改变现有系统&#xff0c;直接在原有系统上实现新功能。该规范于 2007 年发布&#xff0c;是目前业界唯一完整覆盖电商系统各相关业务领域的接口标准…

Flutter运行app时向logcat输出当前打开的界面路径且点击可跳转

当一个项目大了目录文件多了&#xff0c;我们往往会为了找到一个文件花费大量的时间和精力&#xff0c;为了快捷方便的调试我们的项目&#xff0c;我们往往需要在打开app运行的时候需要知道当前打开的界面的文件在哪儿&#xff0c;我们这个代码就能快捷的知道我们app正在打开的…

iTOP-RK3568开发板Windows 安装 RKTool 驱动

在烧写镜像之前首先需要安装 RKTool 驱动。 RKTool 驱动在网盘资料“iTOP-3568 开发板\01_【iTOP-RK3568 开发板】基础资料 \02_iTOP-RK3568 开发板烧写工具及驱动”路径下。 驱动如下图所示&#xff1a; 解压缩后&#xff0c;进入文件夹&#xff0c;如下图所示&#xff1a;…

电缆故障综合测试仪

一、电缆故障查找仪产品简介 本产品用于地埋电缆故障点的快速、企业产品免费信息发布平台定位、电缆埋设路径及埋设深度的电子商务测&#xff08;在故障点处获取深度&#xff09;。 主要特点 1、用特殊结构的声波振动传感器及低噪声专用器件作前置放大&#xff0c;提高了仪器定…