前言
填寫表單時,如果等到按下送出後頁面刷空才告訴你「Email 格式錯誤」,使用者一定會相當崩潰。優良的前端驗證可以在送出時擋下無效請求,並在輸入時即時復原錯誤狀態,大幅節省使用者時間與伺服器資源。
觀念與函式深度解析
1. event.preventDefault() 攔截表單預設送出
為什麼選用這個函式?
原生 在按下送出按鈕或 Enter 時,預設會刷新頁面並將資料發送到 action 網址。在現代單頁應用(SPA)或前端驗證流程中,我們必須呼叫 event.preventDefault() 擋下瀏覽器的預設刷新,改由 JavaScript 來處理驗證與資料發送。
這個函式在幹嘛?
取消瀏覽器對該事件執行的預設動作。
2. 正則表達式(RegExp)格式檢查 (pattern.test(string))
為什麼選用正則表達式?
驗證 Email 格式(例如是否包含 @ 與 .) 或密碼強度(例如最少 8 位數),最嚴謹且有效率的方式就是使用正則表達式。RegExp.test() 會傳回布林值(true/false),非常適合用在條件判斷式中。
核心觀念與語法拆解
event.preventDefault():阻止 表單送出時瀏覽器預設的頁面刷新行為,將主控權交還給 JavaScript 邏輯。
RegExp.test() 格式過濾:使用正則表達式對格式要求嚴謹的欄位(如 Email、手機號碼)進行檢測,搭配 DOM 的 .classList.add('error') 動態高亮問題欄位。
<!DOCTYPE html>
<html lang="zh-TW">
<head>
<meta charset="UTF-8">
<title>第十六課 - 即時表單驗證與錯誤提示</title>
<style>
body { font-family: sans-serif; padding: 40px; background-color: #f8f9fa; }
.form-card { max-width: 400px; margin: 0 auto; background: white; padding: 30px; border-radius: 10px; box-shadow: 0 4px 12px rgba(0,0,0,0.08); }
.form-group { margin-bottom: 20px; }
label { font-weight: bold; color: #333; display: block; margin-bottom: 8px; }
/* 輸入框基本樣式 */
input {
width: 100%;
padding: 10px;
font-size: 15px;
border: 2px solid #ced4da;
border-radius: 6px;
box-sizing: border-box;
outline: none;
transition: border-color 0.2s ease;
}
input:focus { border-color: #007bff; }
/* 驗證失敗時的輸入框與錯誤訊息樣式 */
input.error { border-color: #dc3545; background-color: #fff8f8; }
.error-msg { color: #dc3545; font-size: 13px; margin-top: 5px; display: none; }
.error-msg.show { display: block; }
/* 送出按鈕 */
.submit-btn {
width: 100%;
padding: 12px;
background-color: #007bff;
color: white;
border: none;
border-radius: 6px;
font-size: 16px;
font-weight: bold;
cursor: pointer;
transition: background-color 0.2s ease;
}
.submit-btn:hover { background-color: #0056b3; }
</style>
</head>
<body>
<div class="form-card">
<h2>會員註冊</h2>
<form id="signupForm" novalidate>
<!-- 電子郵件區塊 -->
<div class="form-group">
<label for="emailInput">電子郵件</label>
<input type="email" id="emailInput" placeholder="example@email.com">
<div id="emailError" class="error-msg">請輸入有效的電子郵件格式!</div>
</div>
<!-- 密碼區塊 -->
<div class="form-group">
<label for="passwordInput">密碼 (最少 8 位數)</label>
<input type="password" id="passwordInput" placeholder="請輸入密碼...">
<div id="passwordError" class="error-msg">密碼長度至少需要 8 個字元!</div>
</div>
<button type="submit" class="submit-btn">註冊帳號</button>
</form>
</div>
<script>
// ----------------------------------------------------
// JavaScript 邏輯 (submit 事件攔截與正則表達式驗證)
// ----------------------------------------------------
// 第一步:取得 DOM 元素
const signupForm = document.getElementById("signupForm");
const emailInput = document.getElementById("emailInput");
const passwordInput = document.getElementById("passwordInput");
const emailError = document.getElementById("emailError");
const passwordError = document.getElementById("passwordError");
// Email 的正則表達式 (Basic Email Pattern)
const emailRule = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
// 驗證輔助函式:根據驗證結果切換 UI 錯誤狀態
function validateField(inputEl, errorEl, isValid) {
if (!isValid) {
inputEl.classList.add("error");
errorEl.classList.add("show");
return false;
} else {
inputEl.classList.remove("error");
errorEl.classList.remove("show");
return true;
}
}
// 第二步:監聽表單 submit 事件
signupForm.addEventListener("submit", function(event) {
// 1. 攔截表單預設刷新頁面的行為
event.preventDefault();
// 2. 進行個別欄位驗證
const isEmailValid = validateField(
emailInput,
emailError,
emailRule.test(emailInput.value.trim())
);
const isPasswordValid = validateField(
passwordInput,
passwordError,
passwordInput.value.length >= 8
);
// 3. 通過所有驗證才執行成功邏輯
if (isEmailValid && isPasswordValid) {
alert("驗證成功!表單已準備送出。");
// 這裡後續可以接入 fetch() 將資料傳送至 API
}
});
// 第三步:當使用者重新輸入時,動態清除錯誤狀態 (提升 UX)
emailInput.addEventListener("input", function() {
if (emailRule.test(emailInput.value.trim())) {
validateField(emailInput, emailError, true);
}
});
passwordInput.addEventListener("input", function() {
if (passwordInput.value.length >= 8) {
validateField(passwordInput, passwordError, true);
}
});
</script>
</body>
</html>
總結與實用情境
今天我們建構了完整的表單驗證邏輯流程。掌握「攔截預設行為 ➔ 欄位規則檢測 ➔ 錯誤視覺提示 ➔ 即時復原修正」這套流程,任何登入、註冊、問卷或購物結帳表單都能輕鬆搞定!
下集預告
填寫地址或選取分類時,常常遇到「選了台北市,下一個選區區選單就會自動更新成台北市的行政區」對吧?
【第十七課】表單與輸入:多層級聯動下拉選單(change 事件與動態選單渲染),我們將學習如何處理選單資料間的層級關聯。