新視野行銷企劃

表單與 AJAX 整合:即時驗證與非同步提交

扁平化風格的網頁設計插圖,主題為「表單與 AJAX 整合:即時驗證與非同步提交」,畫面中展示一個網頁表單,含勾選與錯誤圖示、AJAX 對話框及資料交換箭頭,象徵非同步資料傳輸與即時回饋,整體配色現代、乾淨,適合作為技術教學文章封面圖。
在現代 Web 開發中,使用者體驗至關重要。試想,如果使用者輸入了一大堆資訊,提交表單後才發現某個欄位格式錯誤,或帳號名稱已被使用,需要重新整理頁面修正 —— 這種流程無疑令人沮喪。所幸,我們可以透過即時驗證非同步提交提升體驗:在使用者輸入時即給予友善回饋,並使用 AJAX 在背景將資料提交至伺服器,無需重新載入整個頁面。

本文將以步驟導引方式,說明如何使用 jQuery 搭配 PHP 實作表單的即時驗證與非同步提交。範例將涵蓋電子郵件格式驗證、密碼長度檢查,以及帳號名稱即時查重,最後再示範如何將整個表單透過 AJAX 非同步提交至後端處理。一切範例程式碼皆可直接複製使用。讓我們開始吧!

步驟 1:建立 HTML 表單與準備環境

首先,建立一個基本的 HTML 表單骨架,包含需要的輸入欄位和對應的提示元素。我們將實作一個簡單的註冊表單,包括「帳號名稱」、「電子郵件」和「密碼」三個欄位,以及一個提交按鈕。此外,為了即時向使用者顯示驗證結果,每個欄位旁邊會預留一個 <span> 元素來呈現即時訊息(例如錯誤或成功提示)。

同時,請確保已經引入 jQuery 函式庫(可透過 CDN 連結或本機檔案)。在這裡,我們假設使用 CDN 引入最新版的 jQuery,並且會將自訂的 JavaScript 程式碼寫在頁面底部的 <script> 區塊中。

以下是表單的範例 HTML:

HTML
<!-- 引入 jQuery(放在<head>或<body>結尾處,確保在我們的腳本之前載入) -->
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>

<form id="registerForm" action="" method="post">
  <div>
    <label for="username">帳號名稱:</label>
    <input type="text" id="username" name="username" />
    <span id="usernameMsg" class="msg"></span>
  </div>
  <div>
    <label for="email">電子郵件:</label>
    <input type="email" id="email" name="email" />
    <span id="emailMsg" class="msg"></span>
  </div>
  <div>
    <label for="password">密碼:</label>
    <input type="password" id="password" name="password" />
    <span id="passwordMsg" class="msg"></span>
  </div>
  <button type="submit">註冊</button>
</form>

在上述 HTML 中,我們為每個輸入欄位設定了對應的 id 以及 name。id 便於稍後使用 jQuery 進行選取操作,而 name 則是在提交表單時供後端 PHP 取得資料用。此外,每個欄位後的 <span>(帶有 .msg 類別)將用來即時顯示驗證訊息。表單的 id="registerForm" 讓我們能夠針對整個表單綁定提交事件。

步驟 2:表單欄位的即時驗證

現在表單架構就緒,我們要在使用者輸入資訊時即時驗證各欄位的輸入內容。這能讓使用者及早發現問題並立即修正,而不必等提交後才知道出錯。

我們將利用 jQuery 監聽欄位的輸入事件,在以下情況給出即時回饋:

  • 電子郵件格式驗證: 檢查輸入的值是否符合一般電子郵件格式(例如包含 @ 符號及看似有效的網域)。
  • 密碼長度檢查: 確認密碼至少達到一定長度(例如 6 個字元以上),以確保基本的密碼強度。
  • 帳號名稱重複檢查: 透過 AJAX 請求即時查詢伺服器,看看使用者輸入的帳號名稱是否已被註冊。這需要後端配合,我們會建立一個 PHP 腳本接受帳號名稱並返回是否重複。

接下來,將以下 JavaScript 程式碼加入 HTML 中(例如放在前述表單 HTML 下方的 <script> 標籤內)。此程式會在文件載入完成後 ($(document).ready) 綁定各欄位的事件處理函式:

JavaScript / jQuery
<script>
$(function() {
  // 即時電子郵件格式驗證
  $("#email").on("input", function() {
    const emailVal = $(this).val();
    const emailPattern = /^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}$/;
    if (emailVal.length === 0) {
      $("#emailMsg").text("");  // 沒輸入時不顯示任何訊息
    } else if (!emailPattern.test(emailVal)) {
      $("#emailMsg").css("color", "red").text("電子郵件格式不正確");
    } else {
      $("#emailMsg").css("color", "green").text("電子郵件格式正確");
    }
  });

  // 即時密碼長度檢查
  $("#password").on("input", function() {
    const passwordVal = $(this).val();
    if (passwordVal.length === 0) {
      $("#passwordMsg").text("");
    } else if (passwordVal.length < 6) {
      $("#passwordMsg").css("color", "red").text("密碼至少需 6 個字元");

    } else {
      $("#passwordMsg").css("color", "green").text("密碼長度符合要求");
    }
  });

  // 帳號名稱即時重複檢查(使用 AJAX)
  $("#username").on("blur", function() {
    const usernameVal = $(this).val().trim();
    if (usernameVal.length === 0) {
      $("#usernameMsg").text("");
      return; // 若欄位空白就不檢查
    }
    // 發送 AJAX GET 請求到後端檢查帳號名稱
    $.get("check_username.php", { username: usernameVal }, function(response) {
      if (response === "taken") {
        $("#usernameMsg").css("color", "red").text("帳號名稱已被使用");
      } else if (response === "available") {
        $("#usernameMsg").css("color", "green").text("帳號名稱可以使用");
      } else {
        $("#usernameMsg").css("color", "orange").text("發生未知錯誤");
      }
    });
  });
});
</script>

上述程式碼說明:

對於電子郵件欄位,我們使用正規表示式(regex)emailPattern 來驗證輸入格式是否像一個電子郵件地址。每當使用者輸入時(input 事件),即時檢查其值:

  • 若欄位空白,清除任何訊息(避免殘留舊提示)。
  • 若不符合格式,在 #emailMsg 顯示紅色錯誤提示「電子郵件格式不正確」。
  • 若格式正確,則在 #emailMsg 顯示綠色文字「電子郵件格式正確」,讓使用者知道此欄位無誤。

對於密碼欄位,每當輸入時,同樣即時檢查長度:

  • 空白時不提示。
  • 若長度少於 6,則顯示紅色警告「密碼至少需 6 個字元」。
  • 若達到 6 個字元或以上,顯示綠色提示「密碼長度符合要求」。

對於帳號名稱欄位,我們選擇在 blur(失去焦點)時進行檢查,避免使用者每按一個鍵就發出請求:

  • 取得使用者輸入並去除頭尾空白。
  • 如果輸入不空,透過 $.get 發送一個 GET 請求到 check_username.php,將 username 作為參數傳遞。
  • 後端將回傳一個簡單的字串,我們根據 response 的內容更新 #usernameMsg:
    • 若回傳 "taken" 表示帳號已存在,顯示紅色訊息「帳號名稱已被使用」。
    • 若回傳 "available" 表示沒有重複,顯示綠色訊息「帳號名稱可以使用」。
    • 其他情況(例如後端未預期的回應),則以橘色顯示「發生未知錯誤」。

後端 PHP 腳本 (check_username.php):

接著,我們需要編寫對應的 PHP 腳本 check_username.php 來處理上述 AJAX 請求。這個腳本會接受傳來的帳號名稱並檢查是否存在於資料庫或預先定義的清單中。在此範例中,我們以一個簡單的陣列模擬已存在的帳號清單:

PHP
<?php
// 假設此清單代表已註冊的帳號名稱(實務中應改為查詢資料庫)
$existingUsers = ["demo", "test", "admin"];

// 取得 AJAX 傳來的帳號名稱參數
$username = isset($_GET["username"]) ? trim($_GET["username"]) : "";

// 檢查帳號名稱並回傳結果
if ($username === "") {
  echo "empty"; // 若為空白(不應發生,前端已防範)
} elseif (in_array($username, $existingUsers)) {
  echo "taken"; // 帳號名稱已存在
} else {
  echo "available"; // 帳號名稱可使用
}
?>

這段 PHP 程式將帳號名稱與一個預設陣列比較:如果名稱已存在,輸出 "taken";如果不存在,輸出 "available"。前端 JavaScript 收到這個響應後,即可即時告知使用者結果。在實際應用中,你會將這段程式改為查詢資料庫,確認帳號是否真的存在。

透過步驟2的處理,我們已經能在使用者輸入時即時驗證各欄位的有效性並提供回饋。當使用者修正所有欄位並看到綠色的通過訊息後,就可以準備提交整個表單。下一步我們將實作表單的非同步提交。

步驟 3:使用 jQuery 發送 AJAX 提交表單(非同步提交)

即時驗證確保了使用者輸入的資料大致正確,但最終仍需要將資料送往後端儲存或進一步處理。傳統上,按下表單提交按鈕後,瀏覽器會整個頁面跳轉到伺服器返回的新頁面。為了改善體驗,我們將攔截表單的提交事件,改以 AJAX 呼叫來傳送資料,實現非同步提交,也就是在不重新載入頁面的情況下,將表單資料發送給後端。

前端:攔截提交並透過 AJAX 傳送

我們可以利用 jQuery 針對表單的 submit 事件進行攔截。當使用者按下「註冊」按鈕時,我們透過 event.preventDefault() 阻止預設的表單提交行為,然後使用 $.ajax() 將表單資料送到後端的 PHP 腳本進行處理。

將以下程式碼追加到我們之前的 <script> 中(或同一支 JavaScript 檔案中):

JavaScript / jQuery
<script>
$(function() {
  // ...前略,上面的即時驗證代碼...

  // 表單提交事件的處理 - 以 AJAX 傳送表單
  $("#registerForm").on("submit", function(e) {
    e.preventDefault();  // 阻止瀏覽器直接提交表單
    // 準備表單資料
    const formData = $(this).serialize();  // 將表單欄位序列化為 URL 編碼字串
    // 發送 AJAX 請求
    $.ajax({
      url: "process_form.php",   // 後端處理表單的腳本
      type: "POST",
      data: formData,
      success: function(response) {
        if (response === "success") {
          alert("註冊成功!歡迎加入。");
          // 可在此將畫面轉跳或更新為登入狀態等
        } else {
          alert("提交發生錯誤,請稍後再試。");
        }
      },
      error: function() {
        // 如果 AJAX 請求本身失敗(例如網路或伺服器問題)
        alert("無法提交表單,請檢查網路連線或稍後再試。");
      }
    });
  });
});
</script>

說明:

  • 綁定 #registerForm 的 submit 事件,先呼叫 e.preventDefault() 防止瀏覽器進行預設的同步提交。
  • 使用 $(this).serialize() 收集表單所有欄位的值並序列化。這比一項項抓取欄位更方便,確保所有帶 name 屬性的欄位都被包含。
  • 呼叫 $.ajax() 發出 POST 請求:
    • url 指向我們稍後將創建的 PHP 處理腳本(此處為 "process_form.php")。
    • type 設為 "POST" 對應我們想用 POST 方法傳送資料。
    • data 帶入剛剛序列化的表單內容 formData。
    • success 回呼函式會在 PHP 正常回應後執行。response 參數即為伺服器回傳的內容。我們約定如果回傳字串 "success" 代表處理成功,否則視為有錯誤。
      • 若成功,這裡用 alert 提示使用者「註冊成功!」。在真實情境中,你可能改為在表單區域顯示成功訊息,或將頁面轉向登入畫面等。
      • 若非 "success"(例如後端回傳錯誤訊息或其他代碼),則提醒提交發生錯誤。
    • error 回呼函式則在 AJAX 請求本身出現問題時觸發,例如網路中斷或伺服器無回應。我們簡單地用 alert 通知使用者無法提交。

後端:PHP 腳本處理提交資料

前端準備好提交行為後,讓我們撰寫後端的 PHP 腳本 process_form.php 來接收資料並做相應處理。在一個實際的註冊流程中,這支腳本可能需要:

  • 驗證所有必要欄位是否都有值,且格式正確(即便前端驗證過,後端仍要重複驗證以保障安全)。
  • 再次檢查帳號或電子郵件是否已存在(避免繞過前端檢查的狀況)。
  • 將新用戶資料寫入資料庫。
  • 回傳成功或錯誤的狀態。

在此處的簡化範例中,我們不連接真實的資料庫,只做基本的處理和模擬回傳:

PHP
<?php
// 假設這裡已經透過例如 require 引入資料庫連線等前置程式碼

// 取得表單資料
$username = $_POST["username"] ?? "";
$email    = $_POST["email"] ?? "";
$password = $_POST["password"] ?? "";

// 簡單的後端驗證:確認欄位都非空
if ($username === "" || $email === "" || $password === "") {
    echo "error";  // 有必要欄位為空,回傳錯誤
    exit;
}

// TODO: 進一步的驗證(如格式、帳號/電子郵件是否已存在等)
// 例如,可在此查詢資料庫檢查 $username 或 $email 重複

// TODO: 將新使用者資訊寫入資料庫
// 這裡略過實際的資料庫操作,假設寫入成功

// 回傳成功訊息
echo "success";
?>

此 PHP 腳本先讀取 POST 進來的三個欄位資料。接著執行了一個基本檢查:如果任一欄位為空,就輸出 "error" 並結束腳本(在 AJAX success 回呼中會走到錯誤處理邏輯)。你可以擴充這裡的邏輯,檢查格式是否有效、帳號和電子郵件是否早已存在等等。如果所有檢查都通過,並且(在真實情況下)成功將資料存入資料庫,就輸出 "success"。

前端的 AJAX success 函式接收到 "success" 字串後,就會彈出註冊成功的提示給使用者知道。

問與答

在完成以上實作後,開發者可能會有一些疑問,以下整理常見的幾個問題並給出解答:

問:即時驗證已經在前端做了,為什麼後端還需要重複驗證?
答: 前端即時驗證主要是提升使用體驗,快速過濾明顯不符合規則的輸入。然而,使用者可以透過關閉 JavaScript 或直接發送請求繞過前端驗證。因此後端必須再次驗證所有資料的合法性,確保系統安全可靠。兩端驗證相輔相成,提供更佳的體驗與安全性。
問:使用 AJAX 提交表單有什麼好處?如果不用 AJAX 會怎樣?
答: 使用 AJAX 後,表單提交時頁面無需整個重新載入,能即時在前端取得伺服器回應並部分更新介面。這讓操作流程更順暢,使用者體驗更佳。如果不用 AJAX,傳統表單提交會刷新頁面,使用者填寫資料後整個畫面跳轉,不但體驗較差,也比較難在同一頁面上友善地呈現錯誤訊息或結果。
問:$.get 和 $.ajax 以及 $.post 有什麼差別?應該用哪個?
答: $.get 和 $.post 是 jQuery 提供的快捷方法,分別用於發送 GET 或 POST 請求。$.ajax 則是更通用的用法,允許設定更多參數(例如自訂 headers、非同步選項等)。在我們的範例中,即時帳號查重用 $.get 方便地傳遞查詢參數,而提交表單則用 $.ajax 來靈活設定。其實 $.post 也能達成相同效果,你可以寫成:
JavaScript
$.post("process_form.php", formData, function(response) {
    // 處理回應
});
這樣就不用明確指定 type: "POST"。選擇哪個主要看個人喜好和情境,功能上沒有絕對差異。但需要更多客製化時,$.ajax 會比較有彈性。
問:如果使用者的瀏覽器禁用了 JavaScript,該怎麼辦?
答: 如果 JavaScript 被禁用,AJAX 和前端即時驗證都無法運作。為了提高應用的健壯性,應確保表單在無 JavaScript 時仍可以正常提交到後端(可以在 <form> 上保留適當的 action 和 method,以及後端對應處理)。雖然此時使用者體驗較差,但至少功能仍可用。同時,後端的完整驗證在這種情況下更顯重要,因為它成為唯一的防線。
問:可以不用 jQuery,改用原生 JavaScript 的 fetch API 來實作嗎?
答: 可以的。原生的 fetch 或 XMLHttpRequest 都能達成相同效果。使用 jQuery 只是讓程式碼更簡潔,尤其適合熟悉 jQuery 的開發者快速上手。在現代開發中,如果沒有使用 jQuery 的其他功能,很多人也會直接使用 fetch API。兩者各有優勢,但實現的核心思想都是一樣的:在前端發送非同步請求,接收後端回應,再動態更新頁面。

完成以上步驟後,我們成功地將表單即時驗證AJAX 非同步提交整合在一起。使用者在填寫表單時能立即得到回饋,確認資料無誤後點擊提交,又能享受無刷新頁面的順暢體驗。透過這種方式開發的網頁應用,不僅提升了使用便利性,也減輕了伺服器負擔(避免不必要的整頁重新載入)。希望這篇教學能幫助您掌握表單與 AJAX 整合的技巧,在自己的專案中應用出更出色的用戶體驗!

CONTACT US

網站設計報價洽詢

請填寫您的資料,我們將儘快與您聯繫! 為必填