toggleevent 的 newstate 仅在 中有效,popover 不支持该事件及 newstate 属性;监听 details 的 toggle 事件可直接读取 e.newstate,而 popover 需用 :popover-open 伪类判断状态。

ToggleEvent 的 newState 在 <details></details> 中有效,但在 popover 中根本不存在
HTML 的 ToggleEvent 接口目前**只被 <details></details> 元素原生支持**,它的 newState 属性(值为 "open" 或 "closed")可用于可靠判断切换后的状态。而 popover(包括 popover="auto" 和 popover="manual")**不触发 ToggleEvent,也没有 newState 属性**——这是最常被误解的前提错误。
监听 <details></details> 的 toggle 事件并读取 newState
当用户点击 <summary></summary> 或调用 detailsElement.open = true/false 时,<details></details> 会派发 toggle 事件,且事件对象是 ToggleEvent 实例:
<details id="myDetails"><summary>点击查看</summary><p>内容区域</p><div class="aritcle_card flexRow artxards">
<div class="artcardd flexRow">
<a class="aritcle_card_img" rel="nofollow" href="/xiazai/skill6712" title="Wechat HTML Publisher"><img
src="https://img.php.cn/upload/skill/000/000/081/179109368394970.jpg" alt="Wechat HTML Publisher" onerror="this.onerror='';this.src='/static/lhimages/moren/morentu.png'" ></a>
<div class="aritcle_card_info flexColumn">
<a rel="nofollow" href="/xiazai/skill6712" title="Wechat HTML Publisher" class="overflowclass">Wechat HTML Publisher</a>
<p class="overflowclass">直接上传HTML富文本到微信公众号草稿箱。支持完整的HTML格式,无需Markdown转换。</p>
</div>
<a rel="nofollow" href="/xiazai/skill6712" title="Wechat HTML Publisher" class="aritcle_card_btn flexRow flexcenter"><b></b><span>下载</span>
</a>
</div>
</div>
</details><script>
document.getElementById('myDetails').addEventListener('toggle', (e) => {
// ✅ 正确:e 是 ToggleEvent,有 newState
console.log(e.newState); // "open" 或 "closed"
console.log(e.target.open); // 始终与 newState 一致
});
</script>
-
newState是只读属性,反映 DOM 更新后的最终状态,比读e.target.open更语义明确 - 该事件在
open属性完成变更后同步触发,无需setTimeout或requestAnimationFrame - 注意:不要监听
click或change——<details></details>不触发change,click无法区分是 summary 点击还是内部元素点击
popover 没有 ToggleEvent,必须靠 beforetoggle + toggle + 属性轮询
Popover 使用的是 beforetoggle(可取消)和 toggle(不可取消)两个事件,但它们的事件对象是 Event,**没有 newState 属性**。要获知最新状态,需结合以下方式:
<div id="myPopover" popover="auto">弹出内容</div>
<button popovertarget="myPopover">切换</button>
<script>
const popover = document.getElementById('myPopover');
popover.addEventListener('toggle', () => {
// ❌ 错误:e 没有 newState
// console.log(e.newState);
// ✅ 正确:直接读属性(注意:可能有延迟,但已是最可靠方式)
const isOpen = popover.matches(':popover-open');
console.log(isOpen ? 'open' : 'closed');
});
// 或监听 beforetoggle 并检查 popovertargetattribute 变化(更复杂,一般不需要)
</script>
-
:popover-open伪类是当前唯一稳定反映 popover 实际可见状态的 DOM 信号 - 避免依赖
popover.hasAttribute('open')——popover元素本身**从不设置open属性**,它完全由 UA 控制 -
beforetoggle事件中event.state是实验性字段(Chrome 122+),值为"show"/"hide",但尚未标准化,不建议生产环境依赖
兼容性与 polyfill 风险提醒
ToggleEvent.newState 在 Chrome 120+、Firefox 122+、Safari 17.4+ 支持;popover 相关事件在 Chrome 114+、Edge 114+、Safari 17.4+ 支持,Firefox 尚未实现。
- 若需支持旧浏览器,
<details></details>可 fallback 到监听click并手动维护 open 状态变量 - 对 popover 做 polyfill 时,切勿试图模拟
ToggleEvent或添加newState—— 这会导致与原生行为不一致,尤其在嵌套或脚本控制场景下极易出错 - 最易被忽略的一点:
details的toggle事件在open属性通过 JS 设置时也会触发;而 popover 的toggle事件仅在用户交互或showPopover()/hidePopover()调用时触发,不会响应popover.hidden = false等间接操作
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!










