JavaScript 表单验证
1. 客户端验证的两种方式
HTML5 内置验证
HTML5 为表单输入框提供了一套强大的内置验证机制,通过添加特定的属性即可启用:
required
:必填字段。type="email"
/type="url"
:验证字段是否为有效的 Email 或 URL 格式。minlength
/maxlength
:限制文本输入的最小/最大长度。min
/max
:限制数字或日期输入的最小/最大值。pattern
:提供一个正则表达式,用于验证输入值是否匹配特定模式。
<form>
<label for="email">Email:</label>
<input type="email" id="email" name="email" required minlength="8">
<button type="submit">Submit</button>
</form>
当用户尝试提交不符合上述规则的表单时,浏览器会自动显示默认的错误提示气泡。我们还可以使用 CSS 的 :valid
和 :invalid
伪类来为有效和无效的输入框添加样式。
input:invalid {
border: 2px solid red;
}
input:valid {
border: 2px solid green;
}
JavaScript 验证
虽然 HTML5 内置验证很方便,但它的提示信息和外观由浏览器决定,难以自定义,并且无法实现一些复杂的逻辑(如“确认密码”是否与原密码一致)。
为了完全控制验证行为和错误消息的展示,我们需要使用 JavaScript,特别是强大的约束验证 API (Constraint Validation API)。下面我们展开讲解一下这个 API。
3. 约束验证 API
这是一套内建于浏览器、可用于表单元素上的属性和方法的集合。
禁用浏览器默认验证
要使用 JavaScript 全权接管验证,首先需要阻止浏览器默认的验证行为。只需在 <form>
标签上添加 novalidate
属性即可。
<form novalidate>
<!-- 表单内容 -->
</form>
这样,即使用户输入了无效数据,浏览器也不会再弹出默认的错误提示气泡,从而为我们的自定义提示留出空间。
ValidityState 对象:检查验证状态
每个表单字段元素 (如 <input>
) 都有一个只读的 validity
属性。这个属性返回一个 ValidityState
对象,其中包含了一系列布尔值属性,详细描述了该字段当前的验证状态。
validity
对象就像一份输入框的“健康报告”。报告中有很多项,每一项都告诉我们该输入框是否存在某种特定的“病症”。
一些常用的 ValidityState
属性包括:
valid
:如果所有验证都通过,则为true
。这是总的健康状况。valueMissing
:如果字段有required
属性但值为空,则为true
。typeMismatch
:如果type
属性(如email
,url
)的值格式不正确,则为true
。patternMismatch
:如果值不匹配pattern
属性定义的正则表达式,则为true
。tooShort
/tooLong
:如果值的长度小于minlength
或大于maxlength
,则为true
。customError
:如果通过setCustomValidity()
设置了自定义错误,则为true
。
const emailInput = document.getElementById('email');
// 当用户输入时检查
emailInput.addEventListener('input', () => {
if (emailInput.validity.typeMismatch) {
console.log("Please enter a valid email address!");
}
});
validationMessage:获取错误消息
每个表单字段还有一个 validationMessage
属性。它会根据当前失败的验证约束,返回一条由浏览器生成的、本地化的、用户友好的错误消息。
// 如果 email 字段为空,emailInput.validationMessage 可能会是 "Please fill out this field."
// 如果格式不正确,可能会是 "Please include an '@' in the email address."
console.log(emailInput.validationMessage);
核心方法:自定义验证逻辑
-
checkValidity()
- 调用一个表单元素(如
input
)的checkValidity()
方法,会检查该元素的validity.valid
属性。如果为false
,它会触发一个invalid
事件并返回false
;否则返回true
。 - 在
<form>
元素上调用此方法,会检查其内部所有字段的有效性。
- 调用一个表单元素(如
-
setCustomValidity(message)
- 这是最强大的方法,它允许我们设置自定义的错误消息。
- 工作原理:
- 如果你调用
input.setCustomValidity("你的自定义错误消息")
,那么该字段会立即变得无效 (validity.valid
为false
),并且其validationMessage
会变成你设置的消息。 - 如果你调用
input.setCustomValidity("")
(传入一个空字符串),则会清除自定义错误,使该字段恢复到基于 HTML 属性的验证状态。
- 如果你调用
经典案例:验证密码一致性
const password = document.getElementById('password'); const confirmPassword = document.getElementById('confirm-password'); confirmPassword.addEventListener('input', () => { if (password.value !== confirmPassword.value) { // 设置自定义错误 confirmPassword.setCustomValidity("Passwords do not match!"); } else { // 清除自定义错误 confirmPassword.setCustomValidity(""); } });
4. 实践:构建自定义验证流程
下面是一个结合了实时验证和提交时验证的完整示例。
HTML 结构
为每个输入框配备一个用于显示错误消息的 <span>
元素。
<form novalidate>
<div>
<label for="email">Email:</label>
<input type="email" id="email" name="email" required>
<span class="error" aria-live="polite"></span>
</div>
<button type="submit">Submit</button>
</form>
JavaScript 实时验证
在用户输入时或离开字段时提供即时反馈。
const emailInput = document.getElementById('email');
const errorSpan = emailInput.nextElementSibling;
emailInput.addEventListener('input', (event) => {
// 每次用户输入时,检查字段的有效性
if (emailInput.validity.valid) {
// 如果有效,清空错误消息
errorSpan.textContent = '';
errorSpan.className = 'error';
} else {
// 如果无效,显示错误
showError();
}
});
function showError() {
if (emailInput.validity.valueMissing) {
errorSpan.textContent = 'You need to enter an email address.';
} else if (emailInput.validity.typeMismatch) {
errorSpan.textContent = 'Entered value needs to be an email address.';
}
errorSpan.className = 'error active';
}
JavaScript 提交时验证
在用户点击提交按钮时,对整个表单进行最终检查。
const form = document.querySelector('form');
form.addEventListener('submit', (event) => {
// 阻止表单默认的提交行为
event.preventDefault();
// 如果表单无效,显示错误
if (!emailInput.validity.valid) {
showError();
return;
}
// 如果表单有效,可以执行提交逻辑
alert("High five! Form submitted successfully.");
});