如何用JavaScript实现可折叠/展开列表?仅靠类能否实现无分段可折叠列表?
实现仅靠类标记的无额外分段可折叠有序列表
当然可以做这种结构的可折叠列表——不用额外嵌套列表或分段元素,全靠类来区分标题项和子项就行。
第一步:基础样式设置(CSS)
先通过CSS默认隐藏子项,给标题项加可点击的视觉提示,还能加展开/折叠的标识:
/* 默认隐藏所有非标题类的列表项 */ .lesson-item:not(:has(.item-list-section-heading)) { display: none; margin-left: 20px; } /* 标题项样式,提示可点击 */ .lesson-item:has(.item-list-section-heading) { cursor: pointer; font-weight: bold; } /* 给标题项添加展开/折叠的符号标识 */ .lesson-item.expanded:has(.item-list-section-heading)::before { content: "▼ "; } .lesson-item:not(.expanded):has(.item-list-section-heading)::before { content: "▶ "; }
第二步:JavaScript实现折叠/展开逻辑
核心逻辑是:点击标题项时切换自身的展开状态,然后遍历后续的列表项,直到遇到下一个标题项,批量切换这些子项的显示状态:
// 获取所有带标题的列表项 const headingItems = document.querySelectorAll('.lesson-item:has(.item-list-section-heading)'); headingItems.forEach(heading => { // 初始让第一个标题项处于展开状态 if (heading === headingItems[0]) { heading.classList.add('expanded'); toggleSubItems(heading, true); } // 绑定点击事件 heading.addEventListener('click', () => { const isExpanded = heading.classList.toggle('expanded'); toggleSubItems(heading, isExpanded); }); }); // 切换标题项后续子项的显示状态 function toggleSubItems(heading, show) { let nextItem = heading.nextElementSibling; // 遍历后续元素,直到遇到下一个标题项或列表结束 while (nextItem && !nextItem.querySelector('.item-list-section-heading')) { nextItem.style.display = show ? 'list-item' : 'none'; nextItem = nextItem.nextElementSibling; } }
补充说明
- 如果需要兼容不支持
:has()选择器的旧浏览器,可以给子项额外加个类(比如lesson-subitem),把CSS和JS里的选择器替换成对应的类即可,逻辑完全一致。 - 点击标题项时,会自动控制其下方所有子项的显示/隐藏,直到遇到下一个标题项为止。
内容的提问来源于stack exchange,提问作者Talked
相关产品推荐
相关产品推荐

