表单提交后怎么防止用户重复点击提交按钮?
我做了一个用户注册的表单,提交时用的是 fetch 发请求。但发现如果用户手快连点几次“注册”按钮,就会发好几次请求,后端收到了重复数据。我已经试过在点击后给按钮加 disabled,但有时候网络慢,按钮还没变灰就又点了一次,还是防不住。
现在想找个靠谱的办法彻底阻止重复提交,是不是得结合 loading 状态或者加个提交锁?比如这样:
let isSubmitting = false;
form.addEventListener('submit', async (e) => {
e.preventDefault();
if (isSubmitting) return;
isSubmitting = true;
try {
await fetch('/register', { method: 'POST', body: new FormData(form) });
} finally {
isSubmitting = false;
}
});
但不确定这种做法有没有坑,比如页面刷新或者用户中途关闭会不会导致状态卡死?有没有更稳妥的方案?
更稳妥的做法是前后端结合:
前端这边,别只依赖 isSubmitting 标志,按钮要立即禁用,可以先禁用再发请求,别等:
然后关键来了——后端必须做幂等性处理。前端防得住正常用户,防不住手抖和意外。最简单的办法是在表单里加个隐藏的 token 字段,提交时一起传过去,后端用这个 token 做唯一约束,重复提交就直接忽略:
token 可以在页面加载时生成存到 sessionStorage 或者直接埋到表单里:
这样就算用户狂点或者网络超时,后端也不会重复处理数据。前端防一手,后端兜底,双保险。