前言

        重新设计编写一个左侧渲染二级菜单,右侧展示内容的demo项目,内容页包含展示table表格页面,echarts可视化图表页面,后续可能会继续添加页面。


         demo项目的文件构造,如下图

        整体预览图,如下图:


 一、主体页面

        以下为主体  index.html 页面基础代码

<!DOCTYPE html>
<html lang="en">
	<head>
		<meta charset="UTF-8" />
		<meta http-equiv="X-UA-Compatible" content="IE=edge" />
		<meta name="viewport" content="width=device-width, initial-scale=1.0" />
		<title>多级菜单+内容页</title>
		<link rel="stylesheet" href="css/reset.css" />
		<link rel="stylesheet" href="css/style.css" />
		<script src="img/icon/iconfont.js"></script>

		<script src="https://apps.bdimg.com/libs/jquery/2.1.4/jquery.min.js"></script>
	</head>
	<body>
		<!-- 主体 -->
		<div class="content">
			<!-- 菜单 -->
			<div class="content-item menu-section" id="menuSection"></div>
			<!-- 页面 -->
			<div class="content-item page-section">
				<!-- 头部标题部分-->
				<header>
					<h3>秘密小屋</h3>
				</header>
				<div class="iframe-section">
					<iframe name="mainFrame" id="mainFrame" frameborder="1" src=""></iframe>
				</div>
			</div>
		</div>

		<script src="js/index.js"></script>
	</body>
</html>
二、菜单栏及内容页

        预期要实现左侧多级菜单,并且默认展开第一个一级菜单的效果,以及右侧展对应内容页

渲染的 menuData 菜单数组如下,

var menuData = [
	{
		id: "menu1",
		title: "数据可视化图表",
		icon: "echart",
		children: [
			{ id: "menu1-1", title: "柱状图", url: "html/echarts/bar.html" },
			{ id: "menu1-2", title: "饼图", url: "html/echarts/pie.html" },
		],
	},
	{
		id: "menu2",
		title: "表单",
		icon: "table",
		url: "html/table.html",
		children: [
			{ id: "menu2-1", title: "柱状图", url: "html/echarts/bar.html" },
			{ id: "menu2-2", title: "饼图", url: "html/echarts/pie.html" },
		],
	},
	{
		id: "menu3",
		title: "关于我们",
		icon: "about",
		url: "html/about.html",
	},
];

采用原生js来实现渲染效果,svg来渲染图标样式,其index.js文件如下

/**
 * 多级菜单实现
 *
 * 菜单数据:menuData
 */
var menuData = [
	{
		id: "menu1",
		title: "数据可视化图表",
		icon: "echart",
		children: [
			{ id: "menu1-1", title: "折线图", url: "html/echarts/line.html" },
			{ id: "menu1-2", title: "饼图", url: "html/echarts/pie.html" },
			{ id: "menu1-1", title: "柱状图", url: "html/echarts/bar.html" },
		],
	},
	{
		id: "menu2",
		title: "表单",
		icon: "table",
		children: [
			{ id: "menu2-1", title: "非原生table", url: "html/table/notable.html" },
			{ id: "menu2-2", title: "原生table", url: "html/table/Table.html" },
		],
	},
	{
		id: "menu3",
		title: "关于我们",
		icon: "about",
		url: "html/about.html",
	},
];

// 获取渲染菜单和内容区域元素
var menuSection = document.getElementById("menuSection");
var mainFrame = document.getElementById("mainFrame");

// 使用svg图标,图标更丰富
function createIcon(fatherElement, iconSrc) {
	const iconElement = document.createElementNS("http://www.w3.org/2000/svg", "svg");
	iconElement.setAttribute("class", "icon");
	iconElement.setAttribute("aria-hidden", "true");

	const useElement = document.createElementNS("http://www.w3.org/2000/svg", "use");
	useElement.setAttributeNS("http://www.w3.org/1999/xlink", "xlink:href", "#icon-" + iconSrc);

	iconElement.appendChild(useElement);
	fatherElement.appendChild(iconElement);
}

function createMenuItem(menuItem, isExpanded) {
	const liElement = document.createElement("li");

	// 判断是否有图标属性,如果有则添加图标
	if (menuItem.icon) {
		createIcon(liElement, menuItem.icon);
	}

	const titleElement = document.createElement("span");
	titleElement.textContent = menuItem.title;
	titleElement.classList.add("title");

	// 添加 click 事件处理函数
	liElement.addEventListener("click", function (event) {
		event.stopPropagation();

		// 如果有子菜单,则展开/折叠子菜单
		if (menuItem.children) {
			// 首先折叠其他已展开的菜单项
			for (let i = 0; i < menuData.length; i++) {
				const otherMenuItem = menuData[i];
				if (otherMenuItem !== menuItem && otherMenuItem.expanded) {
					otherMenuItem.expanded = false;
					const otherLiElement = menuSection.querySelector(`li[data-id="${otherMenuItem.id}"]`);
					const otherUlElement = otherLiElement.querySelector(".submenu");
					otherUlElement.style.display = "none";
				}
			}

			// 切换当前菜单项的展开状态
			menuItem.expanded = !menuItem.expanded;

			// 根据展开状态设置子菜单的 display 样式
			const ulElement = liElement.querySelector(".submenu");
			ulElement.style.display = menuItem.expanded ? "block" : "none";
		} else {
			// 如果点击的是没有子菜单的菜单项,则加载对应的URL
			const url = menuItem.url;
			if (url) {
				mainFrame.src = url;
			}

			// 切换选中状态
			const selectedItems = menuSection.getElementsByClassName("selected");
			for (let i = 0; i < selectedItems.length; i++) {
				selectedItems[i].classList.remove("selected");
			}
			liElement.classList.add("selected");
		}
	});

	liElement.appendChild(titleElement);

	if (menuItem.children) {
		const ulElement = document.createElement("ul");
		ulElement.classList.add("submenu");

		// 根据展开状态设置子菜单的 display 样式
		ulElement.style.display = isExpanded ? "block" : "none";

		for (let i = 0; i < menuItem.children.length; i++) {
			const childMenuItem = menuItem.children[i];
			const childLiElement = createMenuItem(childMenuItem);
			childLiElement.setAttribute("data-id", childMenuItem.id);
			ulElement.appendChild(childLiElement);
		}

		liElement.appendChild(ulElement);
	} else {
		liElement.setAttribute("data-url", menuItem.url);
	}

	return liElement;
}

// 渲染菜单
function renderMenu(data, parentElement) {
	var ulElement = document.createElement("ul");
	for (var i = 0; i < data.length; i++) {
		var menuItem = data[i];
		const isExpanded = i === 0; // 默认展开第一个菜单项
		var liElement = createMenuItem(menuItem, isExpanded);

		// 如果该菜单项有子菜单,则添加 class="hasChildren" 样式类
		if (menuItem.children) {
			liElement.classList.add("hasChildren");
		}

		ulElement.appendChild(liElement);
	}
	parentElement.appendChild(ulElement);
}

// 初始化菜单
function initMenu() {
	renderMenu(menuData, menuSection);

	// 默认展示第一个包含 url 的子菜单项并选中
	var firstMenuItem = menuData[0];
	var foundFirstUrl = false; // 标志位,表示是否找到第一个包含URL的子菜单项

	if (firstMenuItem && firstMenuItem.children) {
		// 递归函数,用于处理多级菜单情况
		function findFirstUrl(menuItems) {
			for (var i = 0; i < menuItems.length; i++) {
				var menuItem = menuItems[i];

				if (menuItem.url) {
					mainFrame.src = menuItem.url;
					var liElement = menuSection.querySelector('li[data-url="' + menuItem.url + '"]');
					liElement.classList.add("selected");
					foundFirstUrl = true;
					break;
				}

				if (menuItem.children) {
					findFirstUrl(menuItem.children);
					if (foundFirstUrl) {
						break;
					}
				}
			}
		}

		findFirstUrl(firstMenuItem.children);
	}

	// 如果没有找到第一个包含URL的子菜单项,则直接渲染URL
	if (!foundFirstUrl && firstMenuItem.url) {
		mainFrame.src = firstMenuItem.url;
		var liElement = menuSection.querySelector('li[data-url="' + firstMenuItem.url + '"]');
		liElement.classList.add("selected");
	}

	// 点击菜单项展开或收起子菜单
	menuSection.addEventListener("click", function (event) {
		var target = event.target;
		var liElement = target.closest("li");
		if (liElement) {
			// 是否包含子菜单
			var hasChildren = liElement.classList.contains("hasChildren");

			// 获取已展开的菜单项
			var expandedItems = menuSection.querySelectorAll(".expanded");

			// 判断点击的菜单项是否已展开
			var isExpanded = liElement.classList.contains("expanded");

			// 如果菜单项包含子菜单,则阻止默认行为
			if (hasChildren) {
				event.preventDefault();
			}

			// 遍历已展开的菜单项,折叠除当前点击的菜单项以外的其他已展开菜单项
			expandedItems.forEach(function (item) {
				if (item !== liElement && !liElement.contains(item)) {
					item.classList.remove("expanded");
					var submenu = item.querySelector(".submenu");
					submenu.style.display = "none";
				}
			});

			// 如果点击的菜单项是已展开的,则折叠;否则展开
			if (isExpanded) {
				liElement.classList.remove("expanded");
				if (hasChildren) {
					var submenu = liElement.querySelector(".submenu");
					submenu.style.display = "none";
				}
			} else {
				liElement.classList.add("expanded");
				if (hasChildren) {
					var submenu = liElement.querySelector(".submenu");
					submenu.style.display = "block";
					var firstLink = submenu.querySelector("a");
					if (firstLink) {
						firstLink.focus();
					}
				}
			}
		}
	});
}

initMenu();
三、echarts数据可视乎化

        可移步至 echarts官网学习

随便添加几个图表,效果如下图,

         目前只展示折线图页面的设计编码,主体页面为 line.html

<!DOCTYPE html>
<html lang="en">
	<head>
		<meta charset="UTF-8" />
		<meta http-equiv="X-UA-Compatible" content="IE=edge" />
		<meta name="viewport" content="width=device-width, initial-scale=1.0" />
		<title>echarts</title>
		<link rel="stylesheet" href="../../css/reset.css" />
		<link rel="stylesheet" href="../../css/style.css" />
		<script src="../../js/echarts.min.js"></script>
	</head>
	<body>
		<div class="echarts-container">
			<div class="panel panel01">
				<div class="chart"></div>
			</div>
		</div>

		<script src="../../js/initLine.js"></script>
	</body>
</html>

 折现图渲染的js文件  initLine.js,

// 折线图
(function () {
	// 1实例化对象
	var myChart = echarts.init(document.querySelector(".panel01 .chart"));
	var yearData = [
		{
			year: "2092", // 年份
			data: [
				// 两个数组是因为有两条线
				[40, 70, 90, 200, 270, 80, 200, 250, 170, 320],
				[120, 220, 120, 150, 100, 280, 100, 210, 320, 200],
				[300, 320, 280, 370, 400, 400, 300, 400, 280, 450],
				[430, 480, 400, 590, 520, 580, 400, 430, 580, 500],
			],
		},
	];

	option = {
		// 通过这个color修改两条线的颜色
		color: ["#ab285f", "#16406d", "#895d11", "#11c2af"],
		tooltip: {
			trigger: "axis",
		},

		legend: {
			// 如果series 对象有name 值,则 legend可以不用写data
			// 修改图例组件 文字颜色
			textStyle: {
				color: "#527fb5",
			},
			// 这个10% 必须加引号
			right: "10%",
		},
		grid: {
			top: "20%",
			left: "3%",
			right: "4%",
			bottom: "3%",
			show: true, // 显示边框
			borderColor: "#012f4a", // 边框颜色
			containLabel: true, // 包含刻度文字在内
		},
		xAxis: {
			type: "category",
			boundaryGap: false,
			data: ["1月", "2月", "3月", "4月", "5月", "6月", "7月", "8月", "9月", "10月"],
			// 去除刻度线
			axisTick: {
				show: false,
			},
			// 修改x轴上的文字
			axisLabel: {
				color: "#4c9bfd",
			},
			// 去除x轴
			axisLine: {
				show: false,
			},
		},
		yAxis: {
			name: "当日加油/加气量",
			type: "value",
			// 去除刻度线
			axisTick: {
				show: false,
			},
			// 修改y轴上的文字
			axisLabel: {
				fontSize: 12,
				color: "#527fb5",
			},
			// 去除y轴
			axisLine: {
				show: false,
			},
			// y轴分割线的颜色
			splitLine: {
				lineStyle: {
					color: "#012f4a",
				},
			},
		},
		series: [
			{
				name: "92#",
				type: "line",
				// true 可以让我们的折线显示带有弧度
				smooth: true,
				data: yearData[0].data[0],
			},
			{
				name: "95#",
				type: "line",
				smooth: true,
				data: yearData[0].data[1],
			},
			{
				name: "0#",
				type: "line",
				smooth: true,
				data: yearData[0].data[2],
			},
			{
				name: "天然气",
				type: "line",
				smooth: true,
				data: yearData[0].data[3],
			},
		],
	};
	myChart.setOption(option);
	// 4. 让图表跟随屏幕自动的去适应
	window.addEventListener("resize", function () {
		myChart.resize();
		l;
	});
})();
四,table表格

         预期实现表格样式如下图,

     随随便便写了各表格页面内   table.html

<!DOCTYPE html>
<html lang="en">
	<head>
		<meta charset="UTF-8" />
		<meta http-equiv="X-UA-Compatible" content="IE=edge" />
		<meta name="viewport" content="width=device-width, initial-scale=1.0" />
		<title>table表格</title>
		<link rel="stylesheet" href="../../css/reset.css" />
		<link rel="stylesheet" href="../../css/style.css" />
	</head>

	<body>
		<div class="table-container">
			<div class="panel">
				<div class="title">
					<p>原生table</p>
				</div>
				<div class="item-content">
					<div id="table"></div>
				</div>
			</div>
		</div>
		<script src="../../js/initTable.js"></script>
	</body>
</html>

渲染表格 initTable.js

var data = [
	{ id: 1001, name: "张三1", gender: "男", age: 20 },
	{ id: 1002, name: "李四1", gender: "女", age: 11 },
	{ id: 1003, name: "张三2", gender: "男", age: 16 },
	{ id: 1004, name: "李四2", gender: "女", age: 18 },
	{ id: 1005, name: "张三3", gender: "男", age: 14 },
	{ id: 1006, name: "李四3", gender: "女", age: 18 },
	{ id: 1007, name: "张三4", gender: "男", age: 21 },
	{ id: 1008, name: "李四5", gender: "女", age: 18 },
];

var tableHtml = "<table>";
// 添加表头
tableHtml += "<thead><tr>";
tableHtml += "<th>序号</th>";
tableHtml += "<th>姓名</th>";
tableHtml += "<th>性别</th>";
tableHtml += "<th>年龄</th>";
tableHtml += "</tr></thead>";

// 添加表格数据
tableHtml += "<tbody>";
for (var i = 0; i < data.length; i++) {
	tableHtml += "<tr>";
	tableHtml += "<td>" + data[i].id + "</td>";
	tableHtml += "<td>" + data[i].name + "</td>";
	tableHtml += "<td>" + data[i].gender + "</td>";
	tableHtml += "<td>" + data[i].age + "</td>";
	tableHtml += "</tr>";
}
tableHtml += "</tbody></table>";

document.getElementById("table").innerHTML = tableHtml;
五、关于我们

         暂时还没想好写点什么,尽请期待吧

一个跳动的尽请期待,about.html

<!DOCTYPE html>
<html lang="en">
	<head>
		<meta charset="UTF-8" />
		<meta http-equiv="X-UA-Compatible" content="IE=edge" />
		<meta name="viewport" content="width=device-width, initial-scale=1.0" />
		<title>关于我们</title>
		<link rel="stylesheet" href="../css/reset.css" />
		<link rel="stylesheet" href="../css/style.css" />
	</head>
	<body>
		<div class="about-container">
			<div class="note" id="note">尽 请 期 待...</div>
		</div>
		<script>
			var noteElement = document.getElementById("note");

			setInterval(function () {
				// 改变颜色
				var red = Math.floor(Math.random() * 256);
				var green = Math.floor(Math.random() * 256);
				var blue = Math.floor(Math.random() * 256);
				noteElement.style.color = "rgb(" + red + "," + green + "," + blue + ")";
			}, 500); // 这里的 500 表示每隔 0.5 秒改变一次颜色
		</script>
	</body>
</html>

最后

 就这么多吧,之后想起来什么再继续写点吗,嘿嘿嘿,附上了打包文件,快来下载学习吧

附上style.css 样式

body,
html {
	width: 100%;
	height: 100vh;
}

.content {
	width: 100%;
	height: 100%;
	box-sizing: border-box;
	display: flex;
	align-items: flex-start;
	justify-content: flex-start;
}
.content .content-item {
	height: 100%;
}
iframe {
	width: 100%;
	height: 100%;
	border: none;
}

/* 菜单样式开始 */
.content .menu-section {
	width: 15%;
	background-color: rgb(40, 40, 40);
}

ul,
li {
	list-style: none;
}

li {
	text-align: left;
	padding: 8px 0px 8px 10px;
	color: #bdbdbd;
	cursor: pointer;
}

.icon {
	width: 20px;
	height: 20px;
	display: inline-block;
	vertical-align: middle;
	fill: currentColor;
	overflow: hidden;
}

.title {
	padding: 0 0 0 10px;
}

.closed {
	transform: rotate(-90deg);
	transition: all 0.3s ease;
}

.has-children {
	position: relative;
}

.open::before {
	content: "-";
	position: absolute;
	left: -1em;
}

.selected {
	color: #5da8e3;
	background-color: rgba(105, 105, 105, 0.8);
}
.first-level-selected {
	background-color: rgba(105, 105, 105, 0.8);
	color: #5da8e3;
}

.submenu {
	padding: 8px 0px 8px 10px;
}

/* 菜单样式结束 */

/* 页面内容开始 */
.content .page-section {
	width: 85%;
}

.content .page-section header {
	height: 60px;
	text-align: left;
	padding: 0 0 0 60px;
	background-color: #fff;
	/* background-color: rgb(230, 230, 230, 0.8); */
}
.content .page-section header h3 {
	line-height: 60px;
	font-size: 20px;
	color: rgb(97, 97, 97);
}

.content .page-section .iframe-section {
	height: calc(100% - 60px);
	background-color: rgba(241, 241, 241, 0.8);
	overflow: hidden;
}
/* 页面内容结束 */

/* echarts图表样式开始 */
.echarts-container {
	width: 100%;
	height: 100%;
	overflow: hidden;
}
.panel {
	width: 100%;
	height: 100%;
}
.panel .chart {
	width: 100%;
	height: 100%;
}

/* echarts图表样式结束 */

/* table表格样式开始 */
.table-container {
	width: 100%;
	height: 100%;
	overflow: hidden;
}
.table-container .panel {
	width: calc(100% - 100px);
	margin: 0 auto;
}

.table-container .panel .title {
	padding: 20px 0;
	text-align: center;
	font-size: 20px;
	color: #1a2748;
}
.table-container .panel .item-content {
	width: 100%;

	height: 100%;
}

.table-head,
.table-body {
	display: flex;
	align-items: baseline;
}

.table-head {
	background-color: #1a2748;
	padding: 1rem 0;
}

.table-head .head-th {
	flex: 1;
	text-align: center;
	color: #fff;
	font-size: 16px;
}

.table-body,
.body-td {
	flex: 1;
	text-align: center;
	color: #000;
	font-size: 14px;
	padding: 5px 0;
}

.table-body:nth-child(2n) {
	background-color: #0011b342;
}

table {
	width: 100%;
	border-collapse: collapse;
	border-spacing: 0;
	background-color: #f9f9f9;
	font-size: 14px;
	margin-top: 20px;
}
th,
td {
	border: 1px solid #ddd;
	padding: 8px;
	text-align: left;
}
th {
	background-color: #4caf50;
	color: white;
}

/* table表格样式结束 */

/* 关于我们样式开始 */
.about-container {
	width: 100%;
	height: 100%;
	overflow: hidden;
}
.note {
	line-height: 300px;
	text-align: center;
	font-size: 100px;
}
.note {
	animation: jump 0.5s alternate infinite;
}

@keyframes jump {
	0% {
		transform: translateY(0);
	}
	100% {
		transform: translateY(-20px);
	}
}

/* 关于我们样式结束 */

Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐