on:toggle 更可靠,因它是 details 元素原生事件,触发时 e.target.open 状态必与视觉一致;而 click 是底层事件,不保证状态同步,且易受冒泡、子元素等干扰。

toggle 事件不是自定义事件,它是 元素的原生 DOM 事件,Svelte 中直接监听即可,不需要额外声明或 dispatch。
为什么 on:toggle 比 on:click 更可靠
用户点击 时,浏览器会自动触发 toggle 事件,并同步更新 e.target.open 状态;而 click 只反映鼠标动作,不保证 open 属性已更新(尤其在快速连点时容易错判)。
-
toggle是语义化事件:它只在用户主动切换展开/收起状态时触发,且e.target.open值一定与当前视觉状态一致 -
click是底层事件:可能来自 summary 内部任意子元素(比如图标、span),也可能被阻止冒泡干扰,还可能因 focus 移动等副作用提前触发 - Svelte 的
on:toggle绑定无需 polyfill,所有现代浏览器(包括 Safari 12.1+)都原生支持
on:toggle 必须配合 open={...} 而非 bind:open
bind:open 会建立双向绑定,强制将所有 同步到同一个变量,导致单开单关逻辑彻底失效。
- ✅ 正确写法:
open={opened === i}—— 每个独立计算显隐 - ❌ 错误写法:
bind:open={isOpen}—— 所有元素共用一个布尔值,一开全开、一关全关 - ⚠️ 注意:
open是布尔属性,不是事件名;on:toggle是事件监听器,二者职责分离,不能混用
如何在 #each 中安全使用索引控制展开状态
关键在于确保索引 i 稳定可比——不能用 Array(5) 这类无意义占位数组,必须基于真实数据源生成索引。
- 推荐用带业务含义的数组:
const items = [{ id: 'a', title: 'Foo' }, { id: 'b', title: 'Bar' }] - 避免用
Array.from({ length: 3 }).map(...),除非你明确控制了每个项的唯一标识 - 如果数据是动态加载或过滤的,建议改用
id或key字段做状态映射,而不是依赖索引 - 收起时不重置变量:仅在
e.target.open === true时更新opened,否则其他项会自然关闭
最易被忽略的一点:Svelte 不会对 on:toggle 做特殊处理,它就是原生事件。这意味着如果你在 上设置了 disabled 或用了 pointer-events: none,toggle 就不会触发——这和 click 行为一致,但很多人默认它“更高级”,其实它只是更语义、更准时。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











