点击summary无法关闭details下拉框的原因与解决方法
问题原因
这是典型的事件执行时序冲突:
- 你绑在
window上的click监听在事件冒泡阶段触发,运行时会无差别把所有.main-nav__dropdown的open属性设为false,连当前点击的那个<details>也不放过。 - 等你这段自定义回调跑完,浏览器内置的
<details>默认交互逻辑才开始执行:识别到点击的是已展开详情的<summary>,就会切换open状态——因为你刚刚已经把当前组件的open改成了false,原生逻辑一切换就变成了true,最终就表现为点已开下拉的<summary>死活关不上。 - 点组件外部的时候不会触发
<details>的原生切换逻辑,所以你写的全局关闭代码能正常跑通。
修复方案
别在全局点击回调里一刀切关所有下拉,跳过当前点击目标所属的那个下拉,把它的开关完全交给浏览器原生逻辑处理,只关其他不相关的下拉就行,代码如下:
const allDropdowns = document.querySelectorAll(".main-nav__dropdown"); window.addEventListener("click", (e) => { // 找到当前点击事件落在哪个下拉组件里 const currentTargetDropdown = e.target.closest(".main-nav__dropdown"); [...allDropdowns].forEach((dropdown) => { // 当前点的这个下拉让原生toggle逻辑自己处理,不手动改状态 if (dropdown === currentTargetDropdown) return; dropdown.open = false; }); });
改完之后交互完全正常:
- 点组件外任意位置,所有下拉正常关闭
- 点任意下拉的
<summary>,当前下拉正常切换开/关,其他已经展开的下拉会自动收起 - 不需要额外阻止事件冒泡,也不会破坏
<details>原生支持的键盘操作、无障碍访问能力
别用给
<summary>绑事件阻止冒泡的方案修,会搞坏页面里其他依赖事件冒泡的逻辑,还可能影响原生无障碍交互。
内容的提问来源于stack exchange,提问作者user19184856
相关产品推荐
相关产品推荐

