实时验证应优先使用 input 事件而非 blur 或 keyup,因其覆盖所有输入方式;需结合防抖(200ms)、语义化属性(aria-invalid 等)及场景化正则,兼顾性能、无障碍与用户体验。

input 事件监听比 blur 更早触发验证
实时验证的核心是“用户每输一个字符就检查”,input事件正好满足这点——它在输入框内容变化时立即触发,包括键盘输入、粘贴、拖放甚至语音输入。而 blur 只在失焦时触发,已错过大部分交互时机。
常见错误现象:blur下用户输完一整串邮箱才提示“格式错误”,体验断层;或用 keyup 漏掉鼠标粘贴、剪贴板修改等场景。
- 始终优先绑定
input事件,不是change(后者只在失焦 + 值改变时触发) - 对
contenteditable元素或富文本输入框,需额外监听input+compositionend(处理中文输入法上屏) - 移动端要注意:部分安卓浏览器对
input事件有轻微延迟,可加setTimeout(……, 0)确保队列清空
正则校验别硬套通用邮箱 / 手机号模板
直接复制网上“万能邮箱正则”大概率导致误判——比如 test+tag@example.com 是合法邮箱但被拦,或 138****1234 这种脱敏格式被当成有效手机号。
使用场景决定校验粒度:注册页要严格(防机器人),搜索框只需基础格式(防空或明显乱码)。
立即学习 “ 前端免费学习笔记(深入)”;
- 邮箱用
/^[^s@]+@[^s@]+.[^s@]+$/足够覆盖 99% 真实输入,不追求 RFC 5322 全兼容 - 手机号按目标国家写死前缀,比如中国用
^1[3-9]d{9}$,别用^d{11}$(会放过00000000000) - 密码强度建议分阶段提示:“长度 6 位”→“需含数字”→“需含大小写字母”,而不是一次性弹出全部规则
验证状态必须同步更新 DOM 类名和 aria 属性
光改样式不改语义,等于没验证——屏幕阅读器看不到错误,自动化测试抓不到状态,CSS 伪类 :valid/:invalid 也失效。
性能影响很小,但缺失会导致无障碍失败和 E2E 测试频繁挂掉。
- 每次验证后,同步设置
input的aria-invalid("true"/"false")和aria-describedby(指向错误提示 ID) - 用
classList.toggle("error", !isValid)控制类名,避免手动拼接字符串 - 不要仅靠
style.borderColor = "red"标记错误——无 CSS 时完全不可见,且无法被 JS 检测
防抖不是可选项,是必选项
用户快速连打时,input事件每秒可能触发 10+ 次,若每次调用 API 或执行复杂正则,CPU 飙升、响应卡顿、请求堆积,尤其在低配安卓机上明显。
防抖时间设太短(如 50ms)起不到作用,设太长(如 500ms)又让反馈滞后。
- 推荐防抖阈值
200ms:平衡响应速度与资源消耗 - 对异步验证(如用户名是否已被注册),防抖必须作用于整个请求逻辑,不是只包正则
- 注意清除上一次定时器:
clearTimeout(timerRef),否则旧回调可能覆盖新结果
最易被忽略的是:防抖后没处理“验证中”状态。用户输入停顿前看到的是上次结果,中间空白期应显示 aria-busy="true" 或加载态类名,否则会误以为验证失效。






























