Svelte 取消表单 reset,绑定值仍被清空:检查真实点击路径
在 Svelte 5.57.2 中,点击 reset 按钮再于 onreset 取消,可能仍重置绑定状态。把确认放到 reset 之前,并分别检查真实点击与脚本调用。
表单的 onreset 已调用 preventDefault(),用户点击重置按钮后,输入框和绑定状态却仍恢复初值。若脚本调用 form.reset() 时取消又能生效,检查真实点击触发的事件时序。
Svelte 5.57.2 中,下面这类组合仍有问题:
<form onreset={(event) => event.preventDefault()}>
<input bind:value={text} />
<button type="reset">重置</button>
</form>
text 应沿用组件已有的状态声明。这段只展示绑定与取消的位置,不是独立组件。问题针对浏览器真实用户输入路径;用控制台调用或脚本点击得到正常结果,不足以排除。
DOM 没有原生重置,不代表框架状态没重置
Svelte 会在 document 的捕获阶段收到 reset 事件,并安排一个微任务,稍后检查 defaultPrevented、调用表单控件的绑定重置处理。
真实用户输入分发时,微任务检查可能发生在目标表单的 onreset 之前。此时事件尚未被取消,绑定状态已被重置;之后即使浏览器取消原生重置,状态回写仍会清空控件。脚本调用 reset 时分发过程有脚本栈,微任务运行的时机不同,因而出现两种入口表现不一致。
排查时同时记录控件值和组件状态。若只是原生 defaultValue 与初始状态设置不一致,应先处理自己的初始化,不能仅凭“重置后值不对”认定是该时序缺口。
有确认流程时,在触发 reset 前决定
如果 reset 的目的就是“确认后才清空”,可把这项交互改为普通按钮:明确写 type="button",由点击处理先完成确认或业务检查;取消时直接返回,通过后再在该处理里调用目标表单的 reset()。
这样取消分支根本不派发 reset 事件,不依赖 onreset 抢在微任务前执行。保留原本需要在真实重置时运行的事件逻辑,并避免仍有一个会无条件取消 reset 的处理器挡住已确认操作。异步确认期间还要防止重复点击和表单已卸载后继续访问节点。
普通按钮不能省略 type,否则放在表单里可能默认提交。也不要把修复写成逐项给输入框赋空字符串:checkbox、select、初值及其他绑定有各自重置语义,手工清空会改变行为。
如果应用需要支持任何来源的 reset 事件都可在 onreset 中取消,按钮绕行并不能修复该公共契约。保留限制,等待并核对覆盖真实用户事件的正式框架修正;不要在框架内部到处添加延时。
用用户真正的操作验收
保留文字、checkbox 和已有初值,分别用真实鼠标或键盘激活按钮,检查取消后 DOM 与状态都不变,确认后两边都恢复正确值。再检查表单正常提交、脚本重置和组件卸载后的行为。
5.57.2 的正式重置监听仍使用捕获阶段加 Promise 微任务,不能把关于修复的设想当作已发行结果。升级后仍应保留真实交互检查,只有脚本 reset 通过并不能证明原来的取消路径恢复。


