JavaScript折叠面板展开时自动关闭其余面板的实现问题
问题根因
- 你的
closeAll方法错误使用toggle切换所有折叠项的激活状态,而非统一移除激活状态,本身逻辑就存在问题 - 点击事件触发时无论当前点击项是否处于展开状态,都会先执行
closeAll清空所有状态,导致原本展开的项先被关闭,后续再执行toggle又会被重新打开,自然无法实现收起效果 - 重复获取两次
collapsible元素集合属于冗余代码,无需这么写
修正方案
点击时先判断当前项的激活状态再做分支处理:如果当前项已经是展开状态,直接收起即可;如果当前项是未展开状态,先关闭所有其他已展开项,再展开当前项,完整代码如下:
var colls = document.getElementsByClassName("collapsible"); // 关闭除当前点击项外的所有折叠项 function closeOther(currentCol) { for(var col of colls) { // 跳过当前点击的元素,不修改它的状态 if(col === currentCol) continue; col.classList.remove("active"); col.nextElementSibling.style.maxHeight = null; } } for(var col of colls) { col.addEventListener("click", function() { // 先记录当前点击项原本的激活状态,避免后续操作覆盖状态 const isActive = this.classList.contains("active"); // 关闭其他所有已展开的折叠项 closeOther(this); if(isActive) { // 原本就是展开状态,点击后执行收起逻辑 this.classList.remove("active"); this.nextElementSibling.style.maxHeight = null; } else { // 原本是收起状态,点击后执行展开逻辑 this.classList.add("active"); this.nextElementSibling.style.maxHeight = this.nextElementSibling.scrollHeight + "px"; } }); }
逻辑说明
- 替换原有的
closeAll为closeOther方法,遍历折叠项时跳过当前点击的元素,只关闭其他项,不会影响当前项的初始状态判断 - 点击时先记录当前项的初始激活状态,再执行其他项的关闭操作,避免状态被覆盖后无法正确判断用户操作意图
- 不再使用
toggle做模糊的状态切换,根据初始状态明确执行展开/收起操作,避免状态切换混乱
内容的提问来源于stack exchange,提问作者Michael Sims
相关产品推荐
相关产品推荐

