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

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

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

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

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

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

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

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

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

最直觀的做法:點(diǎn)擊后立即禁用提交按鈕。

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('提交失敗,請(qǐng)重試');
    })
    .finally(() => {
      submitBtn.disabled = false;
      submitBtn.textContent = '提交';
    });
});

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

致命缺陷

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

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

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

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

原理:

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

優(yōu)勢(shì)

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

注意:

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

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

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

const pendingRequests = new Set();

function requestWithDedup(key, apiCall) {
  if (pendingRequests.has(key)) {
    console.log('請(qǐng)求正在進(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' })
  );
});

適用場(chǎng)景:

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

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

在大型應(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('請(qǐng)勿重復(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)請(qǐng)求。

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

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

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

結(jié)語(yǔ)

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

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

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

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

相關(guān)文章

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

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

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

    javascript中字符串拼接需注意的問(wèn)題

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

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

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

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

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

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

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

    微信小程序 彈窗自定義實(shí)例代碼

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

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

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

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

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

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

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

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

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

最新評(píng)論

遵义县| 山阳县| 临武县| 岳普湖县| 新田县| 景德镇市| 揭阳市| 白朗县| 阳江市| 丁青县| 云浮市| 牡丹江市| 阿拉善盟| 通渭县| 蓬溪县| 铜陵市| 手游| 开阳县| 长丰县| 台东市| 四平市| 伊吾县| 乃东县| 正蓝旗| 广宁县| 莫力| 汉川市| 临海市| 噶尔县| 凌源市| 呈贡县| 阳曲县| 罗平县| 寻甸| 西安市| 七台河市| 维西| 香河县| 芦山县| 秀山| 江陵县|