vue3+ts+element home页面侧边栏+头部组件+路由组件组合页面教程

在这里插入图片描述

文章目录

  • 效果展示
  • template代码
  • script代码
  • 样式代码


效果展示

在这里插入图片描述

template代码

<template>
	<el-container class="home">
		<el-aside class="flex" :style="{ width: asideDisplay ? '70px' : '290px' }">
			<div class="aside-left">
				<div class="aside-logo">
					<img src="./logo.png" class="aside-logo-img" />
				</div>
				<div class="aside-list">
					<div class="aside-list-item" :class="{ active: item.path === asideActive }"
						v-for="(item, index) in routesList" :key="index" @click="handleRoutes(item)">{{ item.meta.title }}
					</div>
				</div>
			</div>
			<div class="aside-right" :style="{ display: asideDisplay ? 'none' : 'block' }">
				<div class="aside-right-title">Admin.NET</div>
				<div class="aside-right-list">
					<div class="aside-right-list-item" :class="{ active: item.path === currentRoute.children.path }"
						v-for="(item, index) in routesListItem.children" :key="index" @click="handleRoutesItem(item)">{{
							item.meta.title }}</div>
				</div>
			</div>
		</el-aside>
		<el-container class="flex1">
			<el-header class="">
				<div class="header-navbars-container">
					<el-icon v-if="asideDisplay" @click="asideDisplay = !asideDisplay">
						<Expand />
					</el-icon>
					<el-icon v-if="!asideDisplay" @click="asideDisplay = !asideDisplay">
						<Fold />
					</el-icon>
					<el-breadcrumb separator="/">
						<el-breadcrumb-item>{{ currentRoute.meta.title }}</el-breadcrumb-item>
						<el-breadcrumb-item :to="{ path: currentRoute.children.path }">
							{{ currentRoute.children.meta.title }}
						</el-breadcrumb-item>
					</el-breadcrumb>
				</div>
				<div class="header-navbars-tagsview">
					<span class="header-navbars-tagsview-span">
						<span class="header-navbars-tagsview-item" v-for="(item, index) in currentList" :key="index"
							@click="handleRoutes(item)" :class="{ 'active': item.path === currentRoute.children.path }">
							{{ item.meta.title }}
							<!-- {{currentList}} -->
							<el-icon>
								<Close />
							</el-icon>
						</span>
					</span>

				</div>
			</el-header>
			<el-main>
				<router-view></router-view>
			</el-main>
		</el-container>
	</el-container>
</template>

script代码

<script setup lang="ts">
import { reactive, ref, onMounted } from 'vue';
import type { FormInstance, FormRules } from 'element-plus';
import { Expand, Fold, Close } from '@element-plus/icons-vue';
import { useRouter } from 'vue-router';

// 页面加载时
onMounted(() => {
	getAllRoutes();
	firstEnter();
});

const router = useRouter();// 当前页面的路由对象
const routesList = reactive(new Array<any>());
const asideActive = ref('');
const asideDisplay = ref(true);
const routesListItem = reactive({
	meta: { title: '' },
	children: new Array<any>(),
	name: '',
	path: '',

});
const currentRoute = reactive({
	meta: { title: '' },
	children: {
		meta: { title: '' },
		name: '',
		path: '',
	},
	name: '',
	path: '',
});

const currentList = reactive(new Array<any>());


const getAllRoutes = () => {
	const routes = router.getRoutes();
	console.log(routes); // 这里会输出所有的路由记录
	routes.forEach((route: any) => {
		if (route.meta.level == 1) {
			console.log(route);
			routesList.push(route)
		}

	})
	return routes;
};

const firstEnter = () => {
	const value = localStorage.getItem('currentList');
	const value2 = localStorage.getItem('routesListItem');
	const value3 = localStorage.getItem('currentRoute');


	// 检查value是否为null  
	if (value !== null) {
		// 如果value不是null,则尝试解析它  
		try {
			const parsedValue = JSON.parse(value);
			parsedValue.forEach((item: any) => {
				const valFind = currentList.find((val: any) => {
					if (val.name == item.name) {
						return val
					}
				})
				if (!valFind) {
					currentList.push(item)
				}
			});
		} catch (error) {
			// 如果解析过程中发生错误,比如value不是一个有效的JSON字符串,则处理错误  
			console.error('Error parsing JSON:', error);
			currentList.push({
				name: router.currentRoute.value.name,
				path: router.currentRoute.value.path,
				meta: {
					title: router.currentRoute.value.meta.title
				}
			})
		}
	} else {
		// 如果value是null,打印null或者做其他处理  
		console.log(null, 'currentList is null or not set');
		currentList.push({
			name: router.currentRoute.value.name,
			path: router.currentRoute.value.path,
			meta: {
				title: router.currentRoute.value.meta.title
			}
		})
	}

	// 检查value是否为null  
	if (value2 !== null) {
		// 如果value不是null,则尝试解析它  
		try {
			const parsedValue = JSON.parse(value2);
			routesListItem.children = parsedValue.children
			routesListItem.name = parsedValue.name
			routesListItem.path = parsedValue.path
			routesListItem.meta = parsedValue.meta
		} catch (error) {
			// 如果解析过程中发生错误,比如value不是一个有效的JSON字符串,则处理错误  
			console.error('Error parsing JSON:', error);

		}
	} else {
		// 如果value是null,打印null或者做其他处理  
		const parsedValue = router.currentRoute.value.matched[1]
		routesList.forEach(item => {
			if (parsedValue.path.indexOf(item.name) !== -1) {
				routesListItem.children = item.children
				routesListItem.name = item.name
				routesListItem.path = item.path
				routesListItem.meta = item.meta
			}
		})
		console.log(routesListItem, 'routesList');
	}
	if (value3 !== null) {
		// 如果value不是null,则尝试解析它  
		try {
			const parsedValue = JSON.parse(value3);
			currentRoute.children = parsedValue.children
			currentRoute.name = parsedValue.name
			currentRoute.path = parsedValue.path
			currentRoute.meta = parsedValue.meta
			asideActive.value = parsedValue.path
		} catch (error) {
			// 如果解析过程中发生错误,比如value不是一个有效的JSON字符串,则处理错误  
			console.error('Error parsing JSON:', error);
		}
	} else {
		// 如果value是null,打印null或者做其他处理  
		const parsedValue = router.currentRoute.value.matched[2]
		routesListItem.children.forEach(item => {


			if (parsedValue.path.indexOf(item.path) != -1) {
				console.log();

				console.log(item, 'item');
				currentRoute.children = item
				currentRoute.name = routesListItem.name
				currentRoute.path = routesListItem.path
				currentRoute.meta = routesListItem.meta
				asideActive.value = routesListItem.path
			}
		})
		console.log(asideActive, 'currentRoute is null or not set');
	}
};
const handleRoutes = (item: any) => {
	if (item.name == routesListItem.name) {
		asideDisplay.value = !asideDisplay.value
	} else {
		asideDisplay.value = false
		console.log(123123);

	}
	routesListItem.children = item.children
	routesListItem.name = item.name
	routesListItem.path = item.path
	routesListItem.meta = item.meta
	asideActive.value = item.path

	// console.log(routesListItem.valueOf);
};
const handleRoutesItem = (item: any) => {
	router.push(item.path);
	currentRoute.name = routesListItem.name
	currentRoute.path = routesListItem.path
	currentRoute.meta = routesListItem.meta
	currentRoute.children = item
	localStorage.setItem('currentRoute', JSON.stringify(currentRoute));
	localStorage.setItem('routesListItem', JSON.stringify(routesListItem));
	const valFind = currentList.find((val: any) => {
		if (val.name == item.name) {
			return val
		}
	})
	if (!valFind) {
		currentList.push(item)
		localStorage.setItem('currentList', JSON.stringify(currentList));
	}

};


</script>

样式代码

<style lang="scss">
.home {
	width: 100vw;
	height: 100vh;
}

.el-container {
	width: 100%;
	height: 100%;
}

.el-aside {
	min-width: 70px;
	max-width: 290px;
}

.aside-left {
	width: 70px;
	height: 100%;
	background: #2c3a49;

	.aside-logo {
		height: 50px;
		display: flex;
		align-items: center;
		justify-content: center;

		img {
			width: 80%;
			height: 80%;
		}
	}

	.aside-list-item {
		width: calc(100% - 10px);
		height: 40px;
		text-align: center;
		color: #f0f0f0;
		font-size: 12px;
		background: #de291080;
		cursor: pointer;
		margin: 5px;
		border-radius: 5px;
		line-height: 40px;
	}

	.active {
		background: #de2910;
	}
}

.aside-right {
	width: 220px;
	transition: width 0.3s ease;
	border-right: 1px solid #e4e7ed;

	.aside-right-title {
		width: 220px;
		height: 50px;
		display: flex;
		align-items: center;
		justify-content: center;
		box-shadow: rgba(0, 21, 41, 0.02) 0px 1px 4px;
		white-space: nowrap;
		font-weight: 800;
		font-size: 18px;
		color: #11559c;
	}

	.aside-right-list {
		.aside-right-list-item {
			width: 100%;
			height: 50px;
			display: flex;
			align-items: center;
			justify-content: center;
			cursor: pointer;
		}

		.active {
			width: calc(100% - 5px);
			border-right: 5px solid #de2910;
			color: #de2910;
			background-color: #de281027;
		}
	}
}

.el-header {
	padding: 0px;
	height: 100px;
}

.header-navbars-container {
	background-color: #fff;
	border-bottom: 1px solid #f1f2f3;
	position: relative;
	z-index: 1999;
	display: flex;
	height: 60px;

	.el-icon {
		width: 60px;
		height: 60px;
		font-size: 12px;

		svg {
			height: 2em;
			width: 2em;
		}
	}

	.el-breadcrumb {
		// display: flex;
		font-size: 14px;
		line-height: 60px;

		.el-breadcrumb__item {
			align-items: center;
			display: math;
			float: none;
		}
	}
}

.header-navbars-tagsview {
	min-height: 40px;
	padding-right: 20px;
	background-color: #fff;
	border-bottom: 1px solid #f1f2f3;
	overflow: auto;

	.header-navbars-tagsview-span {
		white-space: nowrap;
	}

	.header-navbars-tagsview-item {
		// display: inline-block;
		line-height: 40px;
		margin: 0px 0px 0px 10px;
		font-size: 12px;
		background-color: #de291080;
		padding: 5px 10px;
		color: #fff;
		border-radius: 5px;
		cursor: pointer;
		white-space: nowrap;
	}

	.header-navbars-tagsview-item:hover {
		background-color: #de2810d2;
	}

	.el-icon {
		position: relative;
		top: 2px;
		right: -2px;
	}

	.active {
		background-color: #de2910;
	}
}

.el-main {
	min-width: 1000px;
}
</style>

您好,我是肥晨。
欢迎关注我获取前端学习资源,日常分享技术变革,生存法则;行业内幕,洞察先机。

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

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

相关文章

项目中自动引入神器 - unplugin-auto-import/unplugin-vue-components

前端 项目中 自动引入 神器 前言 在开发中&#xff0c;我们总喜欢站在巨人的肩膀上开发&#xff0c;比如用一些 框架&#xff1a;vue,react, 组件库&#xff1a;element&#xff0c;ant。 工具函数&#xff1a;axios&#xff0c;lodash 现在是模块化时代&#xff0c;我们…

基于SpringBoot后端实现连接MySQL数据库并存贮数据

目录 一、什么是MySQL数据库 二、基于SpringBoot框架连接MySQL数据库 1、首先添加MySQL依赖&#xff1a; 2、配置数据库连接&#xff1a; 3、创建实体类&#xff1a; 4、创建Repository接口&#xff1a; 5、使用Repository&#xff1a; 三、编写业务SQL语句 1、使用Spring Data…

浅模仿小米商城布局(有微调)

CSS文件 *{margin: 0;padding: 0;box-sizing: border-box; }div[class^"h"]{height: 40px; } div[class^"s"]{height: 100px; } .h1{width: 1528px;background-color: green; } .h11{background-color:rgb(8, 220, 8); } .h111{width: 683px;background-c…

异或和之和【蓝桥杯】/拆位+贡献法

异或和之和 拆位贡献法 思路&#xff1a;刚开始考虑遍历L和R&#xff0c;同时可以用一个二维数组存储算过的值&#xff0c;但是时间复杂度还是O(n^2)&#xff0c;所以这种还是要拆位和利用贡献法 可以对于每个位&#xff0c;一定区间内&#xff0c;如果有奇数个1则异或值为1&…

阿里云ECS选型推荐配置

本文介绍构建Kubernetes集群时该如何选择ECS类型以及选型的注意事项。 集群规格规划 目前在创建Kubernetes集群时&#xff0c;存在着使用很多小规格ECS的现象&#xff0c;这样做有以下弊端&#xff1a; 网络问题&#xff1a;小规格Worker ECS的网络资源受限。 容量问题&…

Cubase 8.0 下载地址及安装教程

Cubase是一款流行的音乐制作和音频录制软件&#xff0c;由德国公司Steinberg开发。它是一款专业级的数字音频工作站&#xff08;DAW&#xff09;&#xff0c;广泛应用于音乐制作、音频录制、混音和制作等领域。 Cubase提供了丰富的功能和工具&#xff0c;用于录制、编辑、混音…

ubuntu22.04物理机双系统手动分区

ubuntu22.04物理机双系统手动分区 文章目录 ubuntu22.04物理机双系统手动分区1. EFI系统分区2. 交换分区3. /根分区4. /home分区分区后的信息 手动分区顺序&#xff1a;EFI系统分区(/boot/efi)、交换分区(/swap)、/根分区、/home分区。 具体参数设置&#xff1a; 1. EFI系统分…

Java SPI 机制

SPI 机制的定义 在Java中&#xff0c;SPI&#xff08;Service Provider Interface&#xff09;机制是一种用于实现软件组件之间松耦合的方式。它允许在应用程序中定义服务接口&#xff0c;并通过在类路径中发现和加载提供该服务的实现来扩展应用程序功能。 SPI 机制通常涉及三…

霉霉说地道中文,口型、卡点几乎完美,网友:配音时代结束了?

ChatGPT狂飙160天&#xff0c;世界已经不是之前的样子。 新建了人工智能中文站 每天给大家更新可用的国内可用chatGPT资源 更多资源欢迎关注 「给电影配音的时代即将结束了。」 AI 的发展让很多人直呼饭碗被抢了&#xff0c;以前是艺术家、程序员…… 现在配音员也要失业了&a…

Docker部署一个SpringBoot项目(超级详细)

注意&#xff1a;下面的教程主要是针对 Centos7 的&#xff0c;如果使用的其他发行版会有细微的差别&#xff0c;请查看官方文档。 Docker部署一个SpringBoot项目&#xff08;超级详细&#xff09; 一、安装Docker1.卸载旧版2.配置Docker的yum库3.安装Docker4.设置开机自启动5.…

超级充电测试基础认识

超级充电技术是电动汽车&#xff08;EV&#xff09;充电技术的一种&#xff0c;它的主要目标是在最短的时间内为电动汽车充满电。这种技术的出现&#xff0c;对于推动电动汽车的普及和发展具有重要的意义。 超级充电测试是对超级充电设备和系统进行全面、深入的检查和评估&…

SQL107 将两个 SELECT 语句结合起来(二)(不用union,在where里用or)

select prod_id,quantity from OrderItems where quantity 100 or prod_id like BNBG% order by prod_id;在where子句里使用or

Windows 7 静态 IP 地址

Windows 7 静态 IP 地址 References 静态 IP 地址设置为 192.168.1.198 控制面板 -> 查看网络状态和任务 更改适配器设置 网络连接 -> 属性 TCP / IPv4 警告 - 已计划将多个默认网关用于提供单一网络 (例如 intranet 或者 Internet) 的冗余。 6.1. 关闭 redundancy VMw…

Day23 代码随想录(1刷) 二叉树

669. 修剪二叉搜索树 给你二叉搜索树的根节点 root &#xff0c;同时给定最小边界low 和最大边界 high。通过修剪二叉搜索树&#xff0c;使得所有节点的值在[low, high]中。修剪树 不应该 改变保留在树中的元素的相对结构 (即&#xff0c;如果没有被移除&#xff0c;原有的父代…

Web系统开发之——文章管理

原文地址&#xff1a;Web系统开发之——文章管理 - Pleasure的博客 下面是正文内容&#xff1a; 前言 经过一番考量&#xff0c;关于Web应用系统功能部分的开发&#xff0c;决定采取基础的文字文章管理为核心功能。 不再采取前后端分阶段完成的方式&#xff0c;而是以一个一个…

机器学习模型——KNN

KNN的基本概念&#xff1a; KNN(K-Nearest Neighbor)就是k个最近的邻居的意思&#xff0c;即每个样本都可以用它最接近的k个邻居来代表。KNN常用来处理分类问题&#xff0c;但也可以用来处理回归问题。 核心思想是如果一个样本在特征空间中的k个最相邻的样本中的大多数属于某…

TCPView下载安装使用教程(图文教程)超详细

「作者简介」&#xff1a;CSDN top100、阿里云博客专家、华为云享专家、网络安全领域优质创作者 「推荐专栏」&#xff1a;更多干货&#xff0c;请关注专栏《网络安全自学教程》 TCPView是微软提供的一款「查看网络连接」和进程的工具&#xff0c;常用来查看电脑上的TCP/UDP连接…

水位计在水利工程安全监测中起到的作用

水利工程&#xff0c;作为人类调控水资源、抵御水患以及利用水能的重要工具&#xff0c;其安全性、稳定性与高效性显得尤为关键。水位是水利工程中最基础且至关重要的参数&#xff0c;其精确且实时的监测对于工程的日常运行与管理具有无可替代的重要性。水位计&#xff0c;作为…

多源统一视频融合可视指挥调度平台VMS/smarteye系统概述

系统功能 1. 集成了视频监控典型的常用功能&#xff0c;包括录像&#xff08;本地录像、云端录像&#xff08;录像计划、下载计划-无线导出&#xff09;、远程检索回放&#xff09;、实时预览&#xff08;PTZ云台操控、轮播、多屏操控等&#xff09;、地图-轨迹回放、语音对讲…

ES面试题

1、如何同步索引库 同步调用 在完成数据库操作后&#xff0c;直接调用搜索服务提供的接口 异步通知 在完成数据库操作后&#xff0c;发送MQ消息 搜索服务监听MQ&#xff0c;接收到消息后完成数据修改 监听binlog 2、分词器 ik分词器 ik_smart ik_max_word 自定义分词器 以拼…