首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計綜合問答

表單重複提交防禦:正確禁用提交按鈕的 JS 模式

     編輯:程式設計綜合問答

錯誤示範:直接在 submit 事件中禁用按鈕

$("form").on("submit", function() {
    $(this).find("input[type=submit]").prop("disabled", true); // 錯誤!表單尚未提交,按鈕已禁用 → 瀏覽器取消提交
    return true;
});

原因: HTML 表單提交機制要求提交按鈕在提交瞬間處於**啟用狀態**。JS 設定 `disabled=true` 會立即生效,導致瀏覽器認為「無有效提交按鈕」而中止提交。

正確模式一:旗標變數防重 (最通用、無相依)

var submitting = false; // 模組級旗標
$("form").on("submit", function(e) {
    if (submitting) {
        e.preventDefault(); // 阻止瀏覽器預設提交
        return false;
    }
    submitting = true;
    // 可選:UI 反饋
    var $btn = $(this).find("input[type=submit], button[type=submit]");
    $btn.prop("disabled", true).val("提交中...");
    // 表單正常提交 (非 AJAX),頁面將跳轉/重載,旗標隨頁面釋放
    // 若為 AJAX 提交,需在 complete/error 回調中重置 submitting = false
});

正確模式二:AJAX 提交時的完整流程

$("form").on("submit", function(e) {
    e.preventDefault(); // 1. 先阻止預設提交,完全由 JS 控制
    var $form = $(this), $btn = $form.find(":submit");
    if ($btn.prop("disabled")) return; // 2. 雙重防禦
    
    $btn.prop("disabled", true).data("orig-text", $btn.val()).val("提交中...");
    
    $.ajax({
        url: $form.attr("action"),
        type: $form.attr("method") || "POST",
        data: $form.serialize(),
        success: function(resp) {
            // 成功處理...
        },
        error: function() {
            // 錯誤處理...
        },
        complete: function() {
            // 3. 无论成败,恢复按钮
            $btn.prop("disabled", false).val($btn.data("orig-text") || "提交");
        }
    });
});

HTML5 `required` 驗證與防重結合

瀏覽器原生驗證 (`required`, `pattern`, `type="email"`) 發生在 `submit` 事件**之前**。若驗證失敗,`submit` 事件不會觸發,旗標也不會被設定,**完全相容**,無需額外處理。

原答案核心思想總結

「設置個變量,當這個變量為0時就讓它提交同時這個變量加1;然後在提交事件裡寫個if判斷當這個變量不為零時讓這個按鈕不能被點擊然後返回false」

即 **旗標變數 + 事件攔截** 模式,為經典且有效的防重方案。

進階:後端冪等性保障 (終極防線)

  • 前端防重只能阻擋「手快點兩下」,無法防禦「網路重發」、「中間人重放」、「多標籤頁並發」。
  • **後端必須實作冪等性**:
    ① 資料庫唯一索引 (訂單號、業務流水號)
    ② 分散式鎖 (Redis SETNX)
    ③ Token 機制 (前端獲取 Token → 提交攜帶 Token → 後端 Redis 驗證並刪除 Token)

前端旗標 + 後端冪等 = 完整的重複提交防禦體系。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved