递归函数通过自调用处理嵌套菜单树,核心是遍历每个节点的children字段并递归渲染子项,终止条件为children不存在或为空数组,最终生成带层级class的HTML字符串。

用递归函数实现不限层级的菜单树,核心是让函数能自己调用自己处理子菜单,关键在于识别并遍历每个节点的 children(或类似字段),并在有子项时继续递归。
明确菜单数据结构
典型的数据格式是一个嵌套对象数组,每个对象至少包含 id、name 和可选的 children 字段:
const menuData = [
{ id: 1, name: '首页' },
{
id: 2,
name: '产品',
children: [
{ id: 21, name: 'Web应用' },
{
id: 22,
name: '移动端',
children: [
{ id: 221, name: 'iOS版' },
{ id: 222, name: 'Android版' }
]
}
]
},
{ id: 3, name: '关于我们' }
];
写一个通用递归渲染函数
以生成 HTML 字符串为例,函数接收菜单数组和当前层级(用于缩进或 class 区分),对每一项:判断是否有 children;有则递归调用自身处理子项;拼接最终结构。
Java项目代码review工具。分析Git变更+完整调用链路上下文,推断业务需求,进行多维度评分和分类汇总,生成完整PRD文档。包含细粒度Java代码审查清单(Null安全、异常处理、Streams、并发、equals/hashCode、资源管理、API设计、性能、MyBatis/ORM、事务边界、SQL/DD...
- 用
Array.map遍历当前层级所有菜单项 - 每项生成
<li>,内部包含链接(<a>)和可能的子菜单容器(<ul>) - 当存在
children且非空时,递归传入item.children,并增加层级标识(如加 class 或缩进) - 避免无限递归:确保递归入口有明确终止条件(即
children不存在或为空数组)
示例代码(生成 HTML 字符串)
以下是一个简洁可用的递归函数:
立即学习“Java免费学习笔记(深入)”;
function renderMenu(items, level = 0) {
if (!Array.isArray(items) || items.length === 0) return '';
return `
<ul class="menu-level-${level}">
${items.map(item => `
<li>
<a href="#${item.id}">${item.name}</a>
${item.children && Array.isArray(item.children) && item.children.length
? renderMenu(item.children, level + 1)
: ''}
</li>
`).join('')}
</ul>
`;
}
// 使用
document.getElementById('nav').innerHTML = renderMenu(menuData);
扩展建议:支持更多场景
-
加 key 或 id 属性:为每个
<li>添加唯一data-id,方便后续事件委托绑定 -
支持自定义字段名:把
children设为参数(如childrenKey = 'children'),提高复用性 -
返回 DOM 节点而非字符串:用
document.createElement构建真实节点,避免 XSS 风险且更利于操作 -
加展开/折叠状态:配合布尔字段(如
expanded: true)控制子菜单显隐,需结合事件监听
children 始终是数组(哪怕为空),否则递归时容易报错;渲染前做一次基础校验更稳妥。

















