今日学习重点
掌握HTML5内置的表单验证机制,实现:
- 客户端即时验证
- 自定义验证规则
- 友好的错误提示
- 减少不必要的服务器请求
内置验证属性
1. 必填字段
<input type="text" required>
<select required>
<option value="">请选择</option>
</select>
2. 格式验证
<!-- 邮箱验证 -->
<input type="email" required>
<!-- 网址验证 -->
<input type="url">
<!-- 正则表达式验证 -->
<input type="text" pattern="[A-Za-z]{3}">
3. 长度限制
<!-- 最小长度 -->
<input minlength="6">
<!-- 最大长度 -->
<textarea maxlength="200"></textarea>
4. 数值范围
<input type="number" min="18" max="99">
<input type="range" min="0" max="100" step="5">
高级验证技巧
1. 自定义错误消息
const emailInput = document.getElementById('email');
emailInput.addEventListener('invalid', () => {
if (emailInput.validity.valueMissing) {
emailInput.setCustomValidity('请填写邮箱地址');
} else if (emailInput.validity.typeMismatch) {
emailInput.setCustomValidity('请输入有效的邮箱格式');
}
});
emailInput.addEventListener('input', () => {
emailInput.setCustomValidity('');
});
2. 实时验证反馈
/* 验证通过样式 */
input:valid {
border-color: green;
}
/* 验证失败样式 */
input:invalid {
border-color: red;
}
/* 获取焦点时取消即时验证 */
input:focus:invalid {
box-shadow: none;
}
3. 表单提交拦截
document.querySelector('form').addEventListener('submit', (e) => {
if (!e.target.checkValidity()) {
e.preventDefault();
// 显示自定义错误提示
}
});
验证API详解
ValidityState对象
const input = document.querySelector('input');
console.log(input.validity);
包含以下布尔属性:
- valueMissing:值为空
- typeMismatch:类型不匹配
- patternMismatch:正则不匹配
- tooLong/tooShort:长度问题
- rangeUnderflow/rangeOverflow:数值越界
- stepMismatch:不符合step值
- valid:是否全部通过验证
注意事项
- 安全提醒:前端验证可被绕过必须配合服务器端验证敏感数据(如密码)必须服务器验证
- 兼容性考虑:旧版IE支持有限移动端浏览器行为可能不同
- 用户体验:避免过早验证(如用户正在输入时)错误提示要明确具体
实战案例
1. 密码强度验证
<input type="password" id="password" pattern="(?=.*\d)(?=.*[a-z])(?=.*[A-Z]).{8,}">
<div id="password-strength">
<span>强度:</span>
<span id="strength-level">弱</span>
</div>
<script>
const password = document.getElementById('password');
const level = document.getElementById('strength-level');
password.addEventListener('input', () => {
const val = password.value;
if (val.length === 0) {
level.textContent = '';
} else if (val.length < 4) {
level.textContent = '极弱';
} else if (!/\d/.test(val)) {
level.textContent = '弱';
} else if (!/[A-Z]/.test(val)) {
level.textContent = '中';
} else {
level.textContent = '强';
}
});
</script>
2. 表单分步验证
<form id="multi-step-form">
<!-- 第一步 -->
<div class="step" data-step="1">
<input type="email" required>
<button type="button" onclick="validateStep(1)">下一步</button>
</div>
<!-- 第二步 -->
<div class="step" data-step="2" hidden>
<input type="password" required>
<button type="submit">提交</button>
</div>
</form>
<script>
function validateStep(step) {
const currentStep = document.querySelector(`[data-step="${step}"]`);
const inputs = currentStep.querySelectorAll('input');
let isValid = true;
inputs.forEach(input => {
if (!input.checkValidity()) {
input.reportValidity();
isValid = false;
}
});
if (isValid) {
currentStep.hidden = true;
document.querySelector(`[data-step="${step + 1}"]`).hidden = false;
}
}
</script>
3. 自定义验证组件
<div class="custom-validator">
<input type="text" id="username" required>
<div class="error-message" aria-live="polite"></div>
</div>
<script>
const username = document.getElementById('username');
const errorMsg = document.querySelector('.error-message');
username.addEventListener('blur', () => {
if (username.validity.valueMissing) {
errorMsg.textContent = '用户名不能为空';
} else if (username.value.length < 4) {
errorMsg.textContent = '用户名至少4个字符';
} else {
errorMsg.textContent = '';
}
});
</script>
记住:好的表单验证就像严格的老师——既要阻止错误,又要耐心解释问题所在。前端验证是为了用户体验,后端验证是为了数据安全,两者缺一不可!就像程序员调试代码——先看控制台错误,再查服务器日志。