4.2 表单属性与验证
4.2 表单属性与验证
表单验证体系架构
HTML5引入了完整的客户端表单验证机制,通过组合使用输入类型、属性和约束验证API,开发者可以在不依赖JavaScript的情况下实现基础验证,同时保留完整的自定义验证能力。
1. 核心验证属性
| 属性 | 适用输入类型 | 验证规则 |
|---|---|---|
required |
所有 | 字段不能为空 |
minlength |
text, email, password等 | 最小字符数 |
maxlength |
text, email, password等 | 最大字符数 |
min |
number, range, date等 | 最小值 |
max |
number, range, date等 | 最大值 |
step |
number, range, date等 | 数值间隔 |
pattern |
text, email, password等 | 正则表达式匹配 |
验证属性深度解析
1. 必填字段验证 required
实现示例:
<label for="username">用户名:</label>
<input type="text" id="username" name="username" required>
特性说明:
- 触发条件:表单提交时
- 错误类型:
valueMissing - 兼容性:所有现代浏览器
2. 长度限制验证
组合使用示例:
<label for="password">密码:</label>
<input type="password"
id="password"
name="password"
minlength="8"
maxlength="20"
required>
验证逻辑:
- 先检查
required - 再验证
minlength/maxlength - 错误类型:
tooShort或tooLong
3. 数值范围验证
日期范围示例:
<label for="event-date">活动日期:</label>
<input type="date"
id="event-date"
name="eventDate"
min="2023-01-01"
max="2023-12-31">
数字步进示例:
<label for="quantity">数量:</label>
<input type="number"
id="quantity"
name="quantity"
min="1"
max="10"
step="1"
value="1">
4. 模式匹配验证 pattern
信用卡验证示例:
<label for="credit-card">信用卡号:</label>
<input type="text"
id="credit-card"
name="cardNumber"
pattern="[0-9]{13,16}"
title="请输入13-16位数字信用卡号">
常用正则模式:
- 手机号:
pattern="1[3-9]\d{9}" - 中文姓名:
pattern="[\u4e00-\u9fa5]{2,4}" - 身份证号:
pattern="\d{17}[\dXx]"
约束验证API应用
1. ValidityState对象
属性全集:
interface ValidityState {
valueMissing: boolean; // 违反required
typeMismatch: boolean; // 类型不匹配(email/url等)
patternMismatch: boolean; // 违反pattern
tooLong: boolean; // 违反maxlength
tooShort: boolean; // 违反minlength
rangeUnderflow: boolean; // 小于min
rangeOverflow: boolean; // 大于max
stepMismatch: boolean; // 不符合step
badInput: boolean; // 无效输入(如number输入字母)
customError: boolean; // 有自定义错误
valid: boolean; // 是否有效
}
实战应用:
const emailInput = document.getElementById('email');
emailInput.addEventListener('input', () => {
if(emailInput.validity.typeMismatch) {
showError('请输入有效的邮箱地址');
} else if(emailInput.validity.valueMissing) {
showError('邮箱地址不能为空');
} else {
clearError();
}
});
2. 自定义验证方法
密码确认示例:
<label for="password">密码:</label>
<input type="password" id="password" required>
<label for="confirm-pwd">确认密码:</label>
<input type="password"
id="confirm-pwd"
oninput="validatePassword()">
JavaScript实现:
function validatePassword() {
const pwd = document.getElementById('password');
const confirm = document.getElementById('confirm-pwd');
if(pwd.value !== confirm.value) {
confirm.setCustomValidity('两次输入的密码不一致');
} else {
confirm.setCustomValidity('');
}
}
用户反馈机制
1. 浏览器默认提示
自定义提示信息:
document.querySelector('form').addEventListener('invalid', (e) => {
const elem = e.target;
if(elem.validity.valueMissing) {
elem.setCustomValidity('请填写此字段');
}
}, true);
样式定制:
/* 有效状态样式 */
input:valid {
border-color: #3a3;
}
/* 无效状态样式 */
input:invalid {
border-color: #e33;
}
/* 焦点状态样式 */
input:focus:invalid {
box-shadow: 0 0 5px rgba(255,0,0,0.5);
}
2. 自定义错误提示
HTML结构:
<div class="form-group">
<label for="username">用户名:</label>
<input type="text" id="username" required>
<span class="error-message" aria-live="polite"></span>
</div>
动态更新:
document.querySelectorAll('input').forEach(input => {
input.addEventListener('input', () => {
const error = input.nextElementSibling;
if(!input.checkValidity()) {
error.textContent = input.validationMessage;
input.setAttribute('aria-invalid', 'true');
} else {
error.textContent = '';
input.setAttribute('aria-invalid', 'false');
}
});
});
高级验证场景
1. 异步验证
用户名查重示例:
document.getElementById('username').addEventListener('blur', async function() {
const response = await fetch(`/check-username?name=${this.value}`);
const { available } = await response.json();
if(!available) {
this.setCustomValidity('用户名已存在');
this.reportValidity();
} else {
this.setCustomValidity('');
}
});
2. 表单提交拦截
完整验证示例:
document.querySelector('form').addEventListener('submit', async (e) => {
e.preventDefault();
const form = e.target;
if(!form.checkValidity()) {
// 触发浏览器原生提示
form.reportValidity();
return;
}
// 自定义验证
if(!await validatePasswords()) {
return;
}
// 提交表单
form.submit();
});
async function validatePasswords() {
// 异步验证逻辑
return true;
}
移动端优化策略
1. 输入模式控制
<!-- 显示数字键盘 -->
<input type="text" inputmode="numeric" pattern="[0-9]*">
<!-- 显示带.com的键盘 -->
<input type="email" inputmode="email">
2. 自动填充优化
<input type="text"
name="address"
autocomplete="street-address"
aria-autocomplete="both">
常用autocomplete值:
name:全名email:电子邮箱tel:电话号码cc-number:信用卡号current-password:当前密码
安全最佳实践
1. 输入过滤
function sanitize(input) {
const div = document.createElement('div');
div.textContent = input;
return div.innerHTML;
}
document.querySelector('input').addEventListener('change', function() {
this.value = sanitize(this.value);
});
2. CSRF防护
<input type="hidden"
name="_csrf"
value="<%= csrfToken %>">
性能优化技巧
1. 延迟验证
// 500ms无输入后再验证
let timeout;
input.addEventListener('input', () => {
clearTimeout(timeout);
timeout = setTimeout(() => {
input.checkValidity();
}, 500);
});
2. 批量DOM操作
// 使用DocumentFragment批量更新错误信息
const fragment = document.createDocumentFragment();
invalidInputs.forEach(input => {
const error = createErrorElement(input);
fragment.appendChild(error);
});
errorContainer.appendChild(fragment);
通过系统化应用这些表单验证技术,开发者可以构建既用户友好又安全可靠的表单交互体验。HTML5验证机制与现代JavaScript的结合,为实现渐进增强的表单验证提供了完整解决方案。
#前端开发
分享于 2025-04-01