如何使用原生JavaScript为ul li的每一级节点添加不同的类名
问题修复方案
原有代码存在多处语法和逻辑错误,以下是可直接运行的修复方案,同时提供适配任意嵌套层级的通用实现:
原有代码错误说明
document.querySelector仅返回单个匹配元素,无法直接传入Array.from处理,需替换为document.querySelectorAll匹配所有符合规则的元素setAttribute调用参数错误,第一个参数必须是属性名class,不能直接拼接类名字符串- 第二层循环使用
for...in遍历数组会得到索引值而非DOM元素,需替换为for...of - 手动拼接类名容易产生多余空格、重复类名问题,推荐使用DOM原生的
classList.add方法添加类,兼容性和可靠性更高
修复后的针对性代码(适配你给出的两级嵌套场景)
// 选取所有一级li下直接包含ul的元素 const topLevel = Array.from(document.querySelectorAll(".main-nav-list > li > ul")) .map(ul => ul.parentElement); for (const element of topLevel) { element.classList.add('hasChild', 'top'); // 选取当前一级li下的二级li中包含ul的元素 const subLevel = Array.from(element.querySelectorAll("li > ul")) .map(ul => ul.parentElement); for (const subElement of subLevel) { subElement.classList.add('hasChild', 'sub'); } }
通用递归方案(支持任意层级嵌套,自动按层级分配不同类名)
如果后续菜单嵌套层级增加,可以使用该方案,自动给每一级包含子菜单的li添加level-1、level-2这类带层级标识的类名,同时统一添加hasChild类:
const rootList = document.querySelector('.main-nav > .main-nav-list'); function addLevelClass(liElements, currentLevel) { for (const li of liElements) { // 仅匹配当前li的直接子ul const childUl = li.querySelector(':scope > ul'); if (childUl) { li.classList.add('hasChild', `level-${currentLevel}`); // 递归处理下一级li元素 addLevelClass(Array.from(childUl.children), currentLevel + 1); } } } // 从顶级li开始,层级从1计数 addLevelClass(Array.from(rootList.children), 1);
运行后你提供的HTML结构最终效果为:
- 一级li(原类名a)新增类
hasChild level-1 - 二级li(原类名b)新增类
hasChild level-2
如果后续新增更多嵌套层级,会自动顺延添加对应层级类名。
内容的提问来源于stack exchange,提问作者Script Host
相关产品推荐
相关产品推荐

