表单提交后怎么防止用户重复点击?

Designer°奕诺 阅读 3

我做了一个注册表单,用户点提交后如果网络慢,可能会狂点好几次,结果数据库里插入了多条重复数据。试过在提交后禁用按钮:btn.disabled = true,但有时候请求失败了,按钮就一直禁用,用户没法重试了。

有没有更稳妥的办法?比如只允许提交一次,但失败了又能重新点?下面是我现在的提交逻辑:

form.addEventListener('submit', async (e) => {
  e.preventDefault();
  submitBtn.disabled = true;
  try {
    await fetch('/register', { method: 'POST', body: new FormData(form) });
    alert('注册成功!');
  } catch (err) {
    alert('提交失败,请重试');
    // 这里要不要 enable 按钮?但万一用户又点,会不会重复?
  }
});
我来解答 赞 2 收藏
二维码
手机扫码查看
1 条解答
闲人秀云
这问题很常见,你代码里注释的疑问是对的。catch 里必须启用按钮,不然请求失败用户就卡死了。关键是要在正确的时机启用。

代码给你,用 finally 最稳:

form.addEventListener('submit', async (e) => {
e.preventDefault();

// 防止重复点击
if (submitBtn.disabled) return;

submitBtn.disabled = true;
submitBtn.textContent = '提交中...';

try {
const res = await fetch('/register', {
method: 'POST',
body: new FormData(form)
});

if (!res.ok) throw new Error('请求失败');

alert('注册成功!');
// 成功了可以跳转,或者保持禁用状态
// window.location.href = '/login';
} catch (err) {
alert('提交失败,请重试');
// 失败了必须启用,让用户能重试
submitBtn.disabled = false;
submitBtn.textContent = '提交';
}
// 成功的情况不用 finally,因为成功了按钮就该一直禁用
});


逻辑很简单:成功了按钮保持禁用,失败了就放开让用户重试。开头加个 if (submitBtn.disabled) return 是双重保险,虽然 disabled 的按钮理论上点不了,但有些浏览器或场景可能有坑。

如果想更完善一点,可以加个 loading 状态提示用户别急,用户体验会好很多。另外后端最好也做幂等校验,前端防得住君子防不住小人,接口层用 token 或者唯一标识再拦一道才是正解。
点赞 2
2026-03-02 18:02