使用js动态生成ul和li构建的无限层级菜单,前后端分离项目VUE+阿里巴巴微服务技术栈

最近做了一个项目,后台是无限层级的菜单,那么前端如何无限递归动态生成菜单呢?
自己写了一个递归算法效果如下

在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述

一、代码实现

你只需要知道我的树形数据是什么样就可以了

在这里插入图片描述

subjectTree:[
		{
			id:1,
			title:"计算机",
			parentId:0,
			children:[
				{
					id:2,
					title:"前端",
					parentId:1,
					children:[
						{
							id:3,
							title:"Vue",
							parentId:2
						},
						{
							id:4,
							title:"Html",
							parentId:2
						},
					]
				},
				{
					id:5,
					title:"后端",
					parentId:1,
					children:[
						{
							id:6,
							title:"java",
							parentId:5,
							children:[
								{
									id:100,
									title:"基础",
									parentId:6,
								}
							]
						},
						{
							id:7,
							title:"spring boot",
							parentId:5
						},
					]
				},
			]
		},
		{
			id:8,
			title:"艺术",
			parentId:0,
			children:[
				{
					id:9,
					title:"绘画",
					parentId:8,
					children:[
						{
							id:10,
							title:"素描",
							parentId:9
						},
						{
							id:11,
							title:"色彩",
							parentId:9
						},
					]
				},
			]
		},
	],
然后就是根据数据生成

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

<template>
	<div class="TreeSubject">
		<Section class="c-s-dl">
			<dl class = "nodeDl">
			   <dt><span>课程类别</span></dt>
			   <dd>
				   <ul>
					   <li>
						   <a href="javascript:;">全部</a>
					   </li>
					   <li v-for="item in subjectTree" :key="item.id">
						   <a href="javascript:;" @click="getChildren(item,0)">{{item.title}}</a>
					   </li>
				   </ul>
			   </dd>
			</dl>
		</Section>
	</div>
</template>

<script>
	export default{
		name:"TreeSubject",
		props:{
			subjectTree:{
				type:Array,
				required:true
			}
		},
		data(){
			return{
				
			}
		},
		mounted() {
		},
		methods:{
			getChildren(item,index){//item是每一个课程分类对象,index是层级,0表示根层级
				
				if(!item.children){//如果当前对象没有子节点,不执行逻辑
					return;
				}
				
				const _this=this;//保存this对象
				
				let c_s_dl = document.querySelector(".c-s-dl");//获取容器节点
				let c_s_dl_childNodes = c_s_dl.childNodes;//获取容器所有子节点
				
				if(index == 0){//如果是点击根层级,清除根层级以外所有子层级
					for(let i = c_s_dl_childNodes.length-1;i >= 1;i--){//倒着删,因为删一个length都会变化,这里删除所有不会影响
						c_s_dl.removeChild(c_s_dl_childNodes[i])
					}
				}
				
				if(c_s_dl_childNodes.length>index+1){//如果当前点击层级下面已经有层级,先清除所有子层级
					for(let i = c_s_dl_childNodes.length-1;i >= index+1;i--){//倒着删,因为删一个length都会变化
						c_s_dl.removeChild(c_s_dl_childNodes[i])
					}
				}
				
				let dl = document.createElement("dl");//创建一个dl节点
				let dd = document.createElement("dd");//创建一个dd节点
				let ul = document.createElement("ul");//创建一个ul节点
				
				const cloneData = JSON.parse(JSON.stringify(item.children));// 对源数据深度克隆,拿的是子节点,不深度克隆会改变源数据
				
				for(let i = 0;i < cloneData.length;i++){//遍历所有子节点
				
					let li =document.createElement("li");//创建li
					let a = document.createElement("a");//创建a标签
					
					a.onclick=function(){//添加点击事件
					
						_this.getChildren(cloneData[i],index+1);//同样的添加构建子节点事件
					}
					
					a.innerHTML=cloneData[i].title+"";//为a标签中添加内容
					
					li.appendChild(a)//a标签添加到li
					ul.appendChild(li);//li标签添加到ul
				}
				
				dl.appendChild(dd);//dd添加到dl
				dd.appendChild(ul);//ul添加到dd
				c_s_dl.appendChild(dl)//dl添加到容器
			}
		},
	}
</script>

<style lang="less">
	@import '@/assets/less/clearfix';//引入清除浮动解决高度塌陷less
	.TreeSubject{
		.c-s-dl{
			dl{
				background-color: #F7F7F7;
				height: 50px;
				position: relative;
				dt{
					height: 50px;
					line-height: 50px;
					float: left;
					font-size: 15px;
					color: #777777;
					margin-left: 15px;
				}
				dd{
					display: inline-block;
					height: 50px;
					margin-left: 0px;
					position: absolute;
					left: 100px;
					ul{
						&:extend(.clearfix all);//继承高度塌陷混合
						height: 50px;
						li{
							height: 50px;
							line-height: 50px;
							float: left;
							margin-right: 35px;
							a{
								color: #23272B;
								font-size: 15px;
							}
						}
					}
				}
			}
		}
	}
</style>

没有说到的都是一些基础内容,比如如何添加DOM节点,less样式这些
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
可以使用递归组件来实现无限层级的导航菜单。以下是一个简单的示例代码: ```html <template> <ul> <li v-for="item in menuData" :key="item.id"> <a v-if="item.children" @click.prevent="toggle(item)"> {{ item.name }} <span v-if="item.expanded">-</span> <span v-else>+</span> </a> <a v-else>{{ item.name }}</a> <recursive-menu v-if="item.children && item.expanded" :menu-data="item.children" /> </li> </ul> </template> <script> export default { name: 'RecursiveMenu', props: { menuData: { type: Array, default: () => [] } }, data() { return { expandedItems: [] } }, methods: { toggle(item) { if (this.expandedItems.includes(item.id)) { this.expandedItems = this.expandedItems.filter(id => id !== item.id) } else { this.expandedItems.push(item.id) } } }, components: { RecursiveMenu: { name: 'RecursiveMenu', props: { menuData: { type: Array, default: () => [] } }, template: ` <ul> <li v-for="item in menuData" :key="item.id"> <a v-if="item.children" @click.prevent="$emit('toggle', item)"> {{ item.name }} <span v-if="item.expanded">-</span> <span v-else>+</span> </a> <a v-else>{{ item.name }}</a> <recursive-menu v-if="item.children && item.expanded" :menu-data="item.children" @toggle="$emit('toggle', $event)" /> </li> </ul> ` } } } </script> ``` 在这个示例中,我们使用了一个名为 `RecursiveMenu` 的递归组件来渲染导航菜单。该组件接受一个名为 `menuData` 的数组作为输入,并将其递归渲染为无限层级的导航菜单。 组件首先遍历 `menuData` 数组中的每个项目,并为每个项目渲染一个列表项。对于具有子菜单项目,我们添加了一个展开/折叠按钮,并在单击时触发 `toggle` 方法来切换其展开状态。如果项目已展开,则显示减号图标,否则显示加号图标。 对于每个具有子菜单项目,我们还使用了另一个 `RecursiveMenu` 组件来递归渲染其子菜单。我们将当前项目的 `children` 属性传递给递归组件,并在 `toggle` 事件中传递当前项目以更新其展开状态。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

殷丿grd_志鹏

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值