使用递归写树形结构

我们可以使用递归地方法写树形菜单栏,树形菜单栏的应用场景有很多,使用递归地方法可以快速地转化数据格式。使用for循环,一次只能到一层,要嵌套,并且数据不一定有几层,但递归的方法可以无限的转化数据格式。

下面我们要写一个树形结构,要求打开页面只有父级显示在页面上,子级默认隐藏,只有有子级的父级才会有下拉箭头,并且鼠标放在选中的内容上有hover效果,选中的元素会和其他的元素有明显的区别。点击父级展开下拉箭头颠倒,子级出现。

HTML中只写了一个结构:

<div class="content">
		</div>

css样式:

<style>
			* {
				margin: 0;
				padding: 0;
			}

			.content {
				width: 200px;
				background-color: #535d62;
			}

			.aline {
				width: 200px;
				height: 40px;
				display: flex;
				line-height: 40px;
			}

			.pic {
				width: 20px;
				height: 20px;
				margin-left: 26px;
				margin-top: 10px;

			}

			.text {
				font-size: 14px;
				color: #ffffff;
				display: flex;
				margin-left: 20px;
			}

			.down {
				width: 16px;
				height: 16px;
				margin-top: 15px;
				margin-left: 50px;
				/*设置所有动画的效果:0.3s 淡出效果*/
				transition: all .3s ease-out;
			}

			/* Hover样式 */
			.aline:hover {
				background-color: #7d7d7d;
				transition: 0.5s;
			}

			.aline:hover .text {
				color: #88baa7;
				transition: 0.5s;
			}

			.aline.selected {
				background-color: #7d7d7d;
				color: #88baa7;
			}

			.childs {
				display: none;
			}

			.down-rotate {
				transform: rotate(180deg);
				/* 可选的过渡效果 */
				transition: transform 0.3s ease;
			}
		</style>

js代码:

// 递归的数据格式转化 
			// 参数: data 表示扁平数据,一维的全部数据
			// 参数: pid 表示数据的父级id 一级数据pid=0
			// 参数: arr 数组,函数出来过后将其返回至调用函数位置,函数处理的结果
			function treeData(data, pid, arr = []) {
				// for循环 遍历数组 
				for (let i in data) {
					// 判断数据的pid是否等于父级的id
					if (data[i].pid == pid) {
						// 把数据放在arr中
						arr.push(data[i]);
						// 把子元素放在父级元素中
						arr[arr.length - 1].children = treeData(data, data[i].id)
					};
				};
				// 返回arr的值
				return arr;
			};
			// 声明变量tree_data 等于所有的父级元素
			let tree_data = treeData(arr, 0);
			console.log(tree_data);

			function tree_menu(data) {
				// 整个背景
				let str = '<div class="content">';
				// for循环遍历数组
				for (let i = 0; i < data.length; i++) {

					// 判断是否有子级
					if (data[i].children.length > 0) {
						// 当有子元素时拼接名称和下拉箭头和拼接图标
						str += `
						<div class="aline" onclick="click_show(this)">
						<img class="pic" src="${data[i].img}" alt="" /><div class="text">${data[i].name}
						<img class="down" src="img/向下箭头_小.png" alt="" />`
						str += `</div>
						</div>
						<div class="childs" style="display:none">
						${tree_menu(data[i].children)}
						</div>`
					} else {
						// 否则只拼接名称
						str += `<div class="aline">
				<img class="pic" src="${data[i].img}" alt="" />
				<div class="text">${data[i].name}</div>
				</div>`
					};
				};
				str += '</div>'
				return str;
			};
			// 在页面内输入
			document.write(tree_menu(tree_data));

			// 用于跟踪当前选中的元素
			let option = null;

			function click_show(e) {
				// 获取下一个同级元素,即包含子项的div
				let childsDiv = e.nextElementSibling;
				// 当前被点击的.aline元素
				let alineElement = e;

				// 如果已经有一个元素被选中,则移除其.selected类
				if (option) {
					option.classList.remove('selected');
				};
				// 更新当前选中的元素
				option = alineElement;

				// 判断如果数据和数据的名称是否为childs
				if (childsDiv && childsDiv.className === 'childs') {
					// 获取当前父元素内的箭头图片
					let downArrow = e.querySelector(".down");

					// 切换子菜单的显示状态
					if (childsDiv.style.display === 'none') {
						// 让子级显示
						childsDiv.style.display = 'block';
						// 添加被选中的样式
						alineElement.classList.add('selected');
						// 旋转箭头
						downArrow.classList.add("down-rotate");
					} else {
						childsDiv.style.display = 'none';
						// 重置箭头
						downArrow.classList.remove("down-rotate");
					};
				};
			};

  • 9
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值