最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

前端防止用戶重復(fù)提交表單的4種可靠方案(附防坑指南)

 更新時間:2026年06月05日 10:48:31   作者:前端Hardy  
防重提交不只是禁用按鈕,需前后端協(xié)同解決電商下單、用戶注冊、支付發(fā)起等關(guān)鍵場景的重復(fù)提交問題,這篇文章主要介紹了前端防止用戶重復(fù)提交表單的4種可靠方案,文中還有一些防坑指南,有需要的朋友可以參考下

別再只靠“禁用按鈕”了!真正的防重提交,需要前后端協(xié)同。

在電商下單、用戶注冊、支付發(fā)起等關(guān)鍵場景中,用戶連點多次“提交”按鈕是再常見不過的行為。

輕則造成數(shù)據(jù)庫寫入多條重復(fù)記錄,重則導(dǎo)致用戶被扣款兩次、庫存超賣——這絕不是危言聳聽。

那么,前端該如何有效防止重復(fù)提交?

本文將從用戶體驗系統(tǒng)可靠性兩個維度,為你梳理 4 種主流方案,并告訴你:為什么“禁用按鈕”遠(yuǎn)遠(yuǎn)不夠?

方案一:提交時禁用按鈕(基礎(chǔ)但必要)

最直觀的做法:點擊后立即禁用提交按鈕。

const submitBtn = document.getElementById('submit-btn');
const form = document.getElementById('my-form');

form.addEventListener('submit', (e) => {
  e.preventDefault();
  
  if (submitBtn.disabled) return; // 防止多次觸發(fā)
  
  submitBtn.disabled = true;
  submitBtn.textContent = '提交中...';

  fetch('/api/submit', { method: 'POST', body: new FormData(form) })
    .then(res => res.json())
    .then(data => {
      alert('提交成功!');
    })
    .catch(err => {
      alert('提交失敗,請重試');
    })
    .finally(() => {
      submitBtn.disabled = false;
      submitBtn.textContent = '提交';
    });
});

優(yōu)點:簡單、直觀、提升 UX。

致命缺陷

  • 用戶刷新頁面后狀態(tài)丟失;
  • 無法阻止通過腳本、Postman 等繞過 UI 的重復(fù)請求;
  • 僅靠前端,防不住!

結(jié)論:這是必備的第一道防線,但絕不能是唯一防線。

方案二:使用防重 Token(推薦!前后端協(xié)同)

這才是企業(yè)級應(yīng)用的標(biāo)準(zhǔn)做法。

原理:

  1. 頁面加載時,后端生成一個一次性 token(如 UUID),并存入 Session 或 Redis;
  2. 前端在表單中攜帶該 token 提交;
  3. 后端收到請求后:
    • 檢查 token 是否存在且未使用;
    • 若有效,則標(biāo)記為“已使用”并處理業(yè)務(wù);
    • 若無效或已用過,直接拒絕。
<!-- 表單中隱藏 token -->
<input type="hidden" name="antiReplayToken" value="a1b2c3d4-5678-90ef..." />
// 提交時無需額外處理,token 隨表單自動發(fā)送

優(yōu)勢

  • 即使用戶刷新、多開標(biāo)簽頁,每個 token 只能用一次;
  • 能防御腳本刷接口、自動化工具攻擊;
  • 與業(yè)務(wù)解耦,通用性強(qiáng)。

注意:

  • Token 必須有時效性(如 5 分鐘過期);
  • 必須由后端生成和校驗,前端不可偽造。

方案三:前端加鎖 + 請求去重(適用于 API 場景)

如果你調(diào)用的是無表單的 API(如點擊“領(lǐng)取優(yōu)惠券”按鈕),可用“請求指紋”去重。

const pendingRequests = new Set();

function requestWithDedup(key, apiCall) {
  if (pendingRequests.has(key)) {
    console.log('請求正在進(jìn)行,忽略重復(fù)');
    return Promise.reject('Duplicate request');
  }

  pendingRequests.add(key);
  return apiCall().finally(() => {
    pendingRequests.delete(key);
  });
}

// 使用示例
document.getElementById('claim-btn').addEventListener('click', () => {
  const userId = 'user_123';
  requestWithDedup(`claim_${userId}`, () =>
    fetch('/api/claim-coupon', { method: 'POST' })
  );
});

適用場景:

  • 按鈕觸發(fā)的獨立操作(非完整表單);
  • 需要防止同一用戶短時間內(nèi)多次觸發(fā)同一操作。

方案四:結(jié)合 loading 狀態(tài) + 全局?jǐn)r截(提升體驗)

在大型應(yīng)用中,可借助狀態(tài)管理(如 Redux、Pinia)或 Axios 攔截器統(tǒng)一處理。

// Axios 示例
let isSubmitting = false;

axios.interceptors.request.use(config => {
  if (config.url === '/api/submit-order') {
    if (isSubmitting) throw new Error('請勿重復(fù)提交');
    isSubmitting = true;
  }
  return config;
});

axios.interceptors.response.use(
  res => {
    if (res.config.url === '/api/submit-order') isSubmitting = false;
    return res;
  },
  err => {
    if (err.config?.url === '/api/submit-order') isSubmitting = false;
    return Promise.reject(err);
  }
);

這種方式適合 SPA 應(yīng)用,能覆蓋所有相關(guān)請求。

最終建議:分層防御,才是王道

層級措施作用
前端 UX 層禁用按鈕 + loading 提示阻止普通用戶誤操作
前端邏輯層請求去重 / 狀態(tài)鎖防止快速連點
后端安全層防重 Token / 冪等設(shè)計根本性防御重復(fù)提交
數(shù)據(jù)庫層唯一索引(如訂單號)最后一道保險

記?。?strong>前端可以被繞過,后端必須守住底線。

結(jié)語

防止重復(fù)提交,不是“加個 disabled 就完事”,而是一套縱深防御體系。

從用戶體驗到系統(tǒng)安全,每一步都不可或缺。

下次當(dāng)你看到“提交中…”的按鈕時,不妨想想:你的系統(tǒng),真的扛得住用戶狂點十次嗎?

到此這篇關(guān)于前端防止用戶重復(fù)提交表單的4種可靠方案的文章就介紹到這了,更多相關(guān)前端防止用戶重復(fù)提交表單內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • layui lay-verify form表單自定義驗證規(guī)則詳解

    layui lay-verify form表單自定義驗證規(guī)則詳解

    今天小編就為大家分享一篇layui lay-verify form表單自定義驗證規(guī)則詳解,具有很好的參考價值,相信我對大家有所幫助。一起跟隨小編過來看看吧
    2019-09-09
  • javascript中字符串拼接需注意的問題

    javascript中字符串拼接需注意的問題

    作為一名.net開發(fā)人員相信大家都知道C#中字符串拼接與StringBuilder的效率差距。
    2010-07-07
  • JavaScript獲取標(biāo)簽的幾種方式小結(jié)

    JavaScript獲取標(biāo)簽的幾種方式小結(jié)

    本文主要介紹了JavaScript獲取標(biāo)簽的幾種方式小結(jié),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-02-02
  • JavaScript中的宏任務(wù)和微任務(wù)執(zhí)行順序

    JavaScript中的宏任務(wù)和微任務(wù)執(zhí)行順序

    在?JavaScript?中,宏任務(wù)和微任務(wù)是指在執(zhí)行代碼的過程中的兩種不同的任務(wù)類型,這篇文章主要介紹了JavaScript中的宏任務(wù)和微任務(wù)執(zhí)行順序,需要的朋友可以參考下
    2022-12-12
  • layui button 按鈕彈出提示窗口,確定才進(jìn)行的方法

    layui button 按鈕彈出提示窗口,確定才進(jìn)行的方法

    今天小編就為大家分享一篇layui button 按鈕彈出提示窗口,確定才進(jìn)行的方法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2019-09-09
  • 微信小程序 彈窗自定義實例代碼

    微信小程序 彈窗自定義實例代碼

    這篇文章主要介紹了微信小程序 彈窗自定義實例代碼的相關(guān)資料,有時候做開發(fā)項目的時候需要根據(jù)客戶需求更改原系統(tǒng)的組件,這里就對小程序中彈窗進(jìn)行更改,需要的朋友可以參考下
    2017-03-03
  • JS實現(xiàn)圖片延遲加載并淡入淡出效果的簡單方法

    JS實現(xiàn)圖片延遲加載并淡入淡出效果的簡單方法

    我們大家都知道,對于一個網(wǎng)站最占用帶寬,最影響頁面顯示速度的東西就是圖片。圖片是很重要的,作為一個站長我們是千方百計的使用各種技巧來優(yōu)化圖片,但其實有一種簡單的方法,只需要幾行代碼就能達(dá)到這種效果。同時還附加一種淡入淡出的顯示效果,下面一起來看看。
    2016-08-08
  • 淺析$(function) ready和onload 的區(qū)別

    淺析$(function) ready和onload 的區(qū)別

    新手剛學(xué)習(xí)js和jq的時候難免會接觸題目所標(biāo)識的相關(guān)內(nèi)容,下面小編通過本教程給大家講解(function) ready和onload 的區(qū)別,感興趣的朋友一起看看吧
    2016-09-09
  • BootStrap CSS全局樣式和表格樣式源碼解析

    BootStrap CSS全局樣式和表格樣式源碼解析

    這篇文章主要為大家詳細(xì)解析了BootStrap圖片樣式、輔助類樣式和CSS組件源碼,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-01-01
  • javascript框架設(shè)計讀書筆記之?dāng)?shù)組的擴(kuò)展與修復(fù)

    javascript框架設(shè)計讀書筆記之?dāng)?shù)組的擴(kuò)展與修復(fù)

    本文是司徒正美的《javascript框架設(shè)計》的第三章第2節(jié)的讀書筆記,本節(jié)主要介紹的是javascript數(shù)組的擴(kuò)展與修復(fù),本文則是選取了其中的重點部分展示給大家。
    2014-12-12

最新評論

达日县| 云浮市| 潜江市| 开鲁县| 河南省| 都江堰市| 钟祥市| 嵩明县| 汉阴县| 大化| 濮阳市| 弥渡县| 武功县| 乃东县| 腾冲县| 大埔区| 崇文区| 南开区| 隆德县| 台北县| 体育| 班玛县| 大姚县| 广汉市| 濮阳市| 绥化市| 康保县| 岐山县| 卢氏县| 汉沽区| 新平| 高陵县| 利津县| 孟村| 盐池县| 怀化市| 乌审旗| 无棣县| 甘谷县| 资中县| 衡水市|