You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何设置details的open属性后添加toggle监听器仍触发回调?

为什么设置details的open属性后添加toggle监听器仍会触发回调?

你的代码如下:

const $details = document.querySelector('.my-details')

const onDetailsToggle = () => {
  console.log('details toggled!')
}

const foo = () => {
  $details.open = true
  $details.addEventListener('toggle', onDetailsToggle, { once: true })
}
foo()

核心原因在于浏览器处理details元素open属性变更的异步逻辑:

  • 当你同步设置$details.open = true时,浏览器不会立即触发toggle事件,而是将事件触发的任务放入微任务队列。
  • 添加事件监听器的操作是同步执行的,会在微任务队列里的事件触发前完成。
  • 等所有同步代码执行完毕后,微任务开始处理,此时toggle事件触发,对应的监听器已经存在,所以onDetailsToggle回调会被执行。

你可以做个验证:把添加监听器的操作放进setTimeout(宏任务)里,此时回调就不会执行了——因为宏任务的执行时机在微任务之后,toggle事件已经触发过了:

const foo = () => {
  $details.open = true
  setTimeout(() => {
    $details.addEventListener('toggle', onDetailsToggle, { once: true })
  }, 0)
}
foo()

内容的提问来源于stack exchange,提问作者Aaron Parisi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.27 11:54:59