details原生不支持排他折叠,需用JS实现:监听toggle事件,在details.open为真时遍历其他details并设other.open = false,排除自身;Vue中推荐用ref控制openIndex并与:open绑定;避免监听click或滥用aria属性破坏原生无障碍支持。

用 details + summary 实现原生排他折叠
HTML 原生的 details 元素默认不支持排他(即点击一个展开时自动收起其他),必须靠 JS 控制。但可以利用其语义结构 + 少量脚本实现干净、无障碍友好的排他逻辑。
关键点是:不能只监听 toggle 事件后简单遍历所有 details,否则会触发自身重复收起,造成闪烁或状态错乱;必须过滤掉当前触发项。
示例逻辑:
document.querySelectorAll('details').forEach(details => {
details.addEventListener('toggle', () => {
if (details.open) {
document.querySelectorAll('details:not(:target)').forEach(other => {
if (other !== details) other.open = false;
});
}
});
});
-
:not(:target)不可靠,实际应改用other !== details判断,避免依赖 URL 锚点 - 必须在
if (details.open)内执行收起,否则点击已展开项收起时,会误触「先收起别人、再收起自己」的多余操作 - 该写法兼容 Safari 12.1+、Chrome 12+、Firefox 49+,Edge 79+
Vue 中用 v-model 管理单个激活索引
如果项目已用 Vue,直接用响应式数据控制比手动操作 DOM 更稳。核心是让所有 details 共享同一个 openIndex,每个只在 index === openIndex 时展开。
注意:不要给 details 绑定 @toggle 后再调 $forceUpdate(),那会破坏响应式链路;应统一由 v-model 或 :open 控制状态。
推荐写法(Vue 3 setup):
const openIndex = ref(null);
const toggleItem = (index) => {
openIndex.value = openIndex.value === index ? null : index;
};
- 点击同一项时设为
null,实现「点开→再点收起」的自然行为 - 用
:open="index === openIndex"绑定,而非v-show,确保语义和屏幕阅读器正确识别折叠状态 - 若需初始展开第一项,设
openIndex.value = 0即可,无需额外 DOM 操作
jQuery 里用 $.fn.collapse 会踩哪些坑?
Bootstrap 的 collapse 插件本身支持 data-parent 实现排他,但很多人漏掉关键约束:父容器必须存在,且所有子 .collapse 必须是它的直系后代。
典型错误写法:
<div id="accordion"> <section><div class="collapse">...</div></section><section><div class="collapse">...</div></section> </div>
- 上面结构中
.collapse不是#accordion的直接子元素,data-parent="#accordion"会失效 - 必须改成 直接放在
#accordion下,或用 JS 初始化时显式传入parent选项- Bootstrap 5 移除了 jQuery 依赖,若混用旧版 JS + 新版 CSS,
data-bs-*和data-*属性容易冲突导致无响应无障碍与键盘操作不能只靠
aria-expanded单纯用 JS 切换
aria-expanded而不联动details.open,会导致屏幕阅读器读出「已展开」但内容不可见,或反之。原生details已内置 ARIA 语义,优先复用它。若必须手写折叠组件(比如要兼容 IE),至少保证三点同步:
- 点击
summary或按钮时,同时切换aria-expanded、aria-hidden(对内容区)、以及真实 DOM 显示/隐藏 - 按空格或回车键应和鼠标点击行为一致,需监听
keydown并preventDefault() - 用
role="region"包裹内容区,并设aria-labelledby指向对应summary的 ID
最省事又合规的做法,还是基于
details做增强——它天生支持键盘、焦点管理、语义暴露,只是缺个排他而已。 - Bootstrap 5 移除了 jQuery 依赖,若混用旧版 JS + 新版 CSS,
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











