js的递归函数——实现可收放的树形菜单

前言

树形菜单是一种常见的网站导航方式,它通常由多个层级的菜单项组成,每个菜单项可以有子菜单项。在JavaScript中,我们可以使用递归函数来实现树形菜单。
树形菜单就是这样的东西,点击上一级,显示下一级,无限循环,一直逐层显示下一级。再次点击,关闭下一级。长的很像树,故名树形菜单。学会这个东西,是不是很酷?
在这里插入图片描述


树形菜单的作用

树形菜单的主要作用是将信息层次化,将复杂的信息结构变得更加清晰和直观。它通常用于展示层级关系比较复杂的数据,如文件目录、网站导航、商品分类等。树形菜单的优点包括:

  1. 层次化展示:树形菜单可以将信息按照层级展示,使用户能够更加清晰地理解信息之间的关系。

  2. 简洁明了:树形菜单的结构简单明了,能够有效地减少信息的冗余,提高页面的整体美观度。

  3. 交互性强:树形菜单可以通过展开和收起节点的方式,使用户能够更加方便地获取所需信息。

  4. 可扩展性好:树形菜单可以根据需要随时添加新的节点,具有很好的扩展性。


创建假数据或者请求接口数据

首先,我们需要一个数据结构来表示树形菜单,通常可以使用嵌套的对象或数组来表示。每个菜单项包含以下属性:

下面是一个假数据:

			const menu = [{
    
    
					label: '家人',
					children: [{
    
    
						label: '爹妈',
						children: [{
    
    
							label: '我',
							children: []
						}]
					}]
				},
				{
    
    
					label: '老师',
					children: [{
    
    
							label: '物理老师',
							children: [{
    
    
								label: '物理老师儿子',
								children: []
							}]
						},
						{
    
    
							label: '化学老师',
							children: [{
    
    
								label: '化学老师儿子',
								children: []
							}]
						}
					]
				},
				{
    
    
					label: '老板',
					children: [{
    
    
						label: '总经理',
						children: [{
    
    
								label: '领导1',
								children: [{
    
    
									label: '韩国分公司',
									children: []
								}]
							},
							{
    
    
								label: '领导2',
								children: [{
    
    
									label: '日本分公司',
									children: []
								}]
							}
						]
					}]
				}
			];

定义递归函数,处理数据

接下来,我们可以定义一个递归函数来遍历这个数据源,并且为每个菜单项添加点击事件。

下面是一个递归函数实现:

			function createMenu(menuData) {
    
    
				const menuEl = document.createElement('ul');

				menuData.forEach(item => {
    
    
					const itemEl = document.createElement('li');
					const labelEl = document.createElement('span');
					labelEl.innerText = item.label;
					itemEl.appendChild(labelEl);

					if (item.children.length > 0) {
    
    
						labelEl.addEventListener('click', () => {
    
    
							if (itemEl.classList.contains('open')) {
    
    
								itemEl.classList.remove('open');
								itemEl.removeChild(itemEl.lastChild);
							} else {
    
    
								itemEl.classList.add('open');
								const submenuEl = createMenu(item.children);
								itemEl.appendChild(submenuEl);
							}
						});
					}
					menuEl.appendChild(itemEl);
				});
				return menuEl;
			}

调用函数,渲染页面

最后,我们可以调用这个函数来生成完整的树形菜单的HTML代码:

			const menuEl = createMenu(menu);
			document.body.appendChild(menuEl);

这里假设树形菜单的容器元素的ID为menu。我们先取出这个元素,然后将生成的HTML代码插入到这个元素的innerHTML属性中,即可显示出树形菜单。


效果展示

在这里插入图片描述


完整代码

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8" />
		<meta name="viewport" content="width=device-width, initial-scale=1">
		<title></title>
		<script src="./js/jquery-3.6.1.js"></script>
		<style></style>
	</head>
	<body>
		<script>
			const menu = [{
     
     
					label: '家人',
					children: [{
     
     
						label: '爹妈',
						children: [{
     
     
							label: '我',
							children: []
						}]
					}]
				},
				{
     
     
					label: '老师',
					children: [{
     
     
							label: '物理老师',
							children: [{
     
     
								label: '物理老师儿子',
								children: []
							}]
						},
						{
     
     
							label: '化学老师',
							children: [{
     
     
								label: '化学老师儿子',
								children: []
							}]
						}
					]
				},
				{
     
     
					label: '老板',
					children: [{
     
     
						label: '总经理',
						children: [{
     
     
								label: '领导1',
								children: [{
     
     
									label: '韩国分公司',
									children: []
								}]
							},
							{
     
     
								label: '领导2',
								children: [{
     
     
									label: '日本分公司',
									children: []
								}]
							}
						]
					}]
				}
			];

			function createMenu(menuData) {
     
     
				const menuEl = document.createElement('ul');

				menuData.forEach(item => {
     
     
					const itemEl = document.createElement('li');
					const labelEl = document.createElement('span');
					labelEl.innerText = item.label;
					itemEl.appendChild(labelEl);

					if (item.children.length > 0) {
     
     
						labelEl.addEventListener('click', () => {
     
     
							if (itemEl.classList.contains('open')) {
     
     
								itemEl.classList.remove('open');
								itemEl.removeChild(itemEl.lastChild);
							} else {
     
     
								itemEl.classList.add('open');
								const submenuEl = createMenu(item.children);
								itemEl.appendChild(submenuEl);
							}
						});
					}

					menuEl.appendChild(itemEl);
				});

				return menuEl;
			}

			const menuEl = createMenu(menu);
			document.body.appendChild(menuEl);
		</script>
	</body>
</html>


猜你喜欢

转载自blog.csdn.net/dyk11111/article/details/129813860
今日推荐