input事件比change更及时,适合实时反馈但需防抖;change仅失焦后触发,用于兜底校验;setcustomvalidity需配合reportvalidity()才显示气泡,pattern不带锚点易误判,键盘提交需preventdefault并同步按钮状态。

input事件监听比change更及时
用户输完再失焦才验证,体验就晚了一拍。用 input 事件能实时捕获每次按键、粘贴、自动填充后的值变化,适合做即时反馈。
- 注意:移动端软键盘回车、中文输入法未确认时,
input仍会触发,但值可能是不完整的拼音或候选词,需配合setTimeout防抖(比如延迟 300ms 再校验) -
change只在失去焦点且值改变后触发,适合提交前兜底校验,不能替代实时反馈 - 不要监听
keydown做验证——它捕获的是按键动作,不是最终值,无法处理粘贴、拖入、自动填充等场景
setCustomValidity() 控制原生提示时机
直接写 input.setCustomValidity("不能为空") 不会立刻弹出气泡,必须配合 reportValidity() 或表单 submit 触发。想“边输边提示”,得手动控制显示逻辑。
- 设为空字符串
input.setCustomValidity("")才表示通过;设为非空字符串即标记为无效 - 浏览器原生气泡只在
submit或显式调用reportValidity()时出现,不会因setCustomValidity自动弹出 - 建议:用
setCustomValidity管理校验状态,用 CSS 类(如.error)+ 旁白元素(aria-live)做界面反馈,别依赖原生气泡做实时提示
pattern 和 required 属性的兼容性陷阱
pattern 是正则,但只在提交时生效,且正则默认不带 ^$ 锚点,容易误判。iOS Safari 对某些 Unicode 字符(如 emoji、中日韩字)的 pattern 支持不一致。
-
pattern="\d+"其实等价于/d+/.test(value),不会强制全匹配,"abc123def" 也能通过——要写成pattern="^\d+$" -
required对<input type="number">无效:空值时浏览器会返回""而非null,但valueAsNumber是NaN,需额外判断 - 密码类字段慎用
pattern做强度校验——正则难覆盖真实弱口令,且错误提示太模糊,不如 JS 分项检查后给明确文案(如“至少1个大写字母”)
防重复提交 + 键盘交互细节
按回车提交是高频操作,但默认行为可能绕过你的实时校验逻辑;按钮禁用后若校验恢复,按钮状态必须同步更新,否则用户卡住。
- 表单
submit事件里务必event.preventDefault(),否则页面刷新会丢掉所有 JS 校验状态 - 禁用提交按钮后,记得同时
aria-disabled="true"和tabindex="-1",否则键盘用户仍可聚焦并按空格触发(尤其 Firefox) - 校验失败时,把焦点移到第一个出错的
input并调用scrollIntoView({block: "nearest"}),避免用户看不到错误提示
input 事件的时机、setCustomValidity 的触发条件、pattern 的隐式匹配规则,三者叠加就容易漏掉边界情况。最常被忽略的是:移动端输入法未上屏、自动填充完成后的状态同步,以及键盘用户对禁用按钮的可访问性响应。前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











