open 是布尔 dom 属性,直接赋值 el.open = true/false 即可控制展开/收起;setattribute('open', ...) 无效,因浏览器只检测属性是否存在;状态监听用 toggle 事件,css 用 details[open] 选择器。

open 是 DOM 属性,不是 HTML 属性 —— 直接赋值就行,别碰 setAttribute。
为什么 el.setAttribute('open', 'false') 反而展开?
因为 open 是布尔属性,浏览器只检测“有没有”,不解析值。只要写了 open=(哪怕右边是 "false"、"" 或 "banana"),就视为存在,强制展开。
-
<details open></details>→ 展开 -
<details open="false"></details>→ 还是展开(常见翻车点) -
<details></details>→ 收起(没写就是没存在)
el.open = true 和 el.open = false 怎么用
直接读写 DOM 元素的 open 属性,它实时反映当前状态,且修改后立即生效。
-
el.open = true→ 立即展开,无需重绘或触发事件 -
el.open = false→ 立即收起,比removeAttribute('open')更可靠 -
console.log(el.open)→ 返回true或false,永远准确 -
el.hasAttribute('open')≠el.open:JS 设置后,HTML 源码没变,所以hasAttribute仍返回false
监听展开/收起变化只能用 toggle 事件
toggle 是唯一能准确捕获状态变更的事件,但它只在用户点击 <summary></summary> 时触发,JS 直接赋值 open 不会派发。
- ✅ 正确写法:
el.addEventListener('toggle', () => console.log(el.open)) - ❌ 别用
change:根本不存在 - ❌ 别绑
click到<summary></summary>:破坏键盘(Enter/Space)和读屏支持 - ⚠️ 注意:
toggle不冒泡,不能委托;IE 完全不支持,需用'open' in document.createElement('details')检测
CSS 响应状态必须用 details[open] 选择器
样式要跟着 DOM 属性走,而不是 HTML 属性或 class —— details[open] 能响应 JS 设置的 open 值,details[open="false"] 无效。
- ✅
details[open] .content { max-height: 200px; } - ✅
details:not([open]) summary::after { content: "▼"; } - ❌
details[open="false"]→ 浏览器根本不识别这个语法 - ⚠️ 关键细节:CSS 的
[open]和 JS 的el.open都走 DOM 属性路径,但hasAttribute()走 HTML 源码路径——混用极易判断错状态
真正容易被忽略的是:JS 设置 el.open = false 后,hasAttribute('open') 依然为 false,而 details[open] 却已失效——这两条“状态感知通道”完全独立,别指望它们同步。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











