Skip to content

表单验证

表单验证确保用户输入在处理或提交之前是正确、完整和有用的。验证可以在客户端(在浏览器中使用 HTML 和 JavaScript)和服务器端进行。

客户端验证为用户提供即时反馈,改善用户体验并减少不必要的服务器负载。然而,它不应是唯一的验证形式,因为它可能会被绕过。始终也要实现服务器端验证。

HTML5 引入了一些输入属性,允许浏览器自动执行基本验证,而无需任何 JavaScript:

  • required:指定输入字段必须填写。
  • type:定义预期的数据类型(例如 email、number、url、date)。浏览器将验证格式。
  • pattern:指定输入值必须匹配的正则表达式。
  • min 和 max:指定数值或日期输入的最小值和最大值。
  • minlength 和 maxlength:指定基于文本的输入的最小和最大长度。

HTML5 内置验证示例:

<form id="myForm">
<label for="email">Email:</label>
<input type="email" id="email" name="email" required>
<label for="age">Age:</label>
<input type="number" id="age" name="age" min="18" max="99" required>
<label for="password">Password (min 8 chars, 1 number, 1 uppercase):</label>
<input type="password" id="password" name="password" required minlength="8"
pattern="(?=.*\d)(?=.*[a-z])(?=.*[A-Z]).{8,}">
<button type="submit">Submit</button>
</form>

浏览器通常会为这些内置验证显示默认的错误消息。

使用 Constraint Validation API 进行 JavaScript 验证

Section titled “使用 Constraint Validation API 进行 JavaScript 验证”

当 HTML5 内置验证不足,或者你需要更定制化的验证逻辑或错误消息时,可以使用 JavaScript。Constraint Validation API 提供了属性和方法来处理表单元素的验证状态。

  • element.validity:一个 ValidityState 对象,包含指示验证状态的布尔属性(例如 validity.valueMissing、validity.typeMismatch、validity.patternMismatch、validity.valid)。
  • element.validationMessage:如果元素无效,则为描述验证错误的本地化消息。
  • element.checkValidity():如果元素有效,返回 true;否则返回 false。如果无效,它还会触发元素的 invalid 事件。
  • form.checkValidity():如果所有表单元素都有效,返回 true;否则返回 false。会触发无效元素的 invalid 事件。
  • element.setCustomValidity(message):允许你设置自定义错误消息。如果消息是空字符串,则认为该元素在自定义错误方面是有效的。如果是非空字符串,则元素无效。

JavaScript 验证示例:

function validateForm(event) {
const form = document.getElementById('userForm'); // 假设表单的 id 是 'userForm'
const usernameInput = document.getElementById('username'); // 假设输入的 id 是 'username'
const feedbackElement = document.getElementById('usernameFeedback'); // 用于显示错误
// 用户名的自定义验证逻辑
if (usernameInput.value.length < 5) {
usernameInput.setCustomValidity('Username must be at least 5 characters long.');
feedbackElement.textContent = usernameInput.validationMessage;
} else {
usernameInput.setCustomValidity(''); // 清除自定义错误
feedbackElement.textContent = '';
}
// 检查整个表单的有效性(包括 HTML5 和自定义检查)
if (!form.checkValidity()) {
event.preventDefault(); // 如果无效,阻止表单提交
// 可选地,显示一般性错误消息或聚焦第一个无效字段
console.log('Form is invalid. Please check the fields.');
// 遍历无效字段并显示消息
Array.from(form.elements).forEach(el => {
if (!el.validity.valid && el.nextElementSibling && el.nextElementSibling.classList.contains('error-message')) {
el.nextElementSibling.textContent = el.validationMessage;
}
});
} else {
console.log('Form is valid and can be submitted.');
// 在这里,你通常会允许表单提交或通过 AJAX 发送数据
// event.preventDefault(); // 如果通过 AJAX 提交
// submitFormData(new FormData(form));
}
}
const myForm = document.getElementById('userForm');
if (myForm) {
myForm.addEventListener('submit', validateForm);
// 可选:添加 'input' 事件监听器以获取实时反馈
const usernameField = document.getElementById('username');
if(usernameField) {
usernameField.addEventListener('input', () => {
if (usernameField.validity.valid) {
usernameField.setCustomValidity('');
const feedback = document.getElementById('usernameFeedback');
if(feedback) feedback.textContent = '';
}
// 可选地,触发 validateForm 或其部分逻辑以获取即时反馈
});
}
}
// 上述示例的 HTML(简化):
// <form id="userForm" novalidate> <!-- 'novalidate' 禁用浏览器默认的气泡提示 -->
// <label for="username">Username:</label>
// <input type="text" id="username" name="username" required>
// <span class="error-message" id="usernameFeedback"></span>
// <button type="submit">Register</button>
// </form>

在 <form> 元素上设置 novalidate 属性会禁用浏览器默认的验证 UI(如错误气泡),允许你实现完全自定义的反馈机制。

数据验证的主要目的是确保数据是:

  • 完整:所有必填字段都已填写。
  • 正确:数据格式正确(例如,有效的电子邮件、年龄为数字)。
  • 一致:数据符合业务规则(例如,密码复杂度)。
  • 安全:通过净化输入防止常见的漏洞,如跨站脚本攻击 (XSS)(主要是服务器端关注的问题,但客户端可以帮助引导用户)。

CSS 提供了伪类(pseudo-classes),允许你根据表单元素的验证状态来设置样式:

选择器描述
:valid选择值有效的输入元素。
:invalid选择值无效的输入元素。
:required选择带有 required 属性的输入元素。
:optional选择没有 required 属性的输入元素。
:in-range选择值在 min 和 max 范围内的输入元素。
:out-of-range选择值在 min 和 max 范围外的输入元素。

为无效字段设置样式的 CSS 示例:

input:invalid {
border-color: red;
background-color: #fff0f0;
}
input:valid {
border-color: green;
}

查看完整列表,请参考 MDN 上的 CSS 伪类。