oninvalid在表单提交或reportValidity()调用时触发,非实时;需配合setCustomValidity()覆盖原生提示,并在oninput中清空以重置验证状态。

oninvalid 事件触发时机与默认行为
表单提交时,required 字段为空、pattern 不匹配、min/max 超限等导致 checkValidity() 返回 false,就会触发 oninvalid。但注意:它**不会在用户输入过程中实时触发**,只在表单提交或显式调用 reportValidity() 时发生。
此时浏览器会显示原生提示(如“请填写此字段”),且该提示无法通过 CSS 修改——除非你主动干预。
- 仅靠
oninvalid="alert('...')"只能弹窗,不阻止原生提示出现 - 原生提示和自定义弹窗会叠加,体验混乱
- IE10+ 支持
oninvalid,但旧版 IE 完全不支持,需降级处理
setCustomValidity() 是核心,不是可选项
真正替换原生提示的,是 setCustomValidity() 方法。它直接修改 input.validity.customError 状态,并覆盖 validationMessage 的值。
关键点在于:一旦调用 setCustomValidity('xxx'),该 input 就永远处于 invalid 状态,直到你显式调用 setCustomValidity('') 清空它——否则即使用户已填入合法内容,表单仍无法提交。
-
setCustomValidity('')是固定写法,传空字符串才表示“无自定义错误” - 传
null或undefined会被转成字符串,等效于setCustomValidity('null'),反而锁死验证 - 必须配合
oninput清空,否则首次报错后,后续输入无效
为什么必须加 oninput="setCustomValidity('')"
这是最容易被忽略、也最常导致 bug 的环节。用户第一次提交失败后,input 的 validity.customError 已为 true,此后无论输入什么,checkValidity() 都返回 false。
oninput 在每次输入变化时触发(包括粘贴、删除、键盘输入),是唯一可靠的机会重置状态。
- 不能用
onkeyup:不捕获粘贴、右键粘贴、语音输入等操作 - 不能只靠
onchange:它只在失焦时触发,用户可能一直不离开输入框 - 移动端需额外注意:iOS Safari 对
oninput触发时机有延迟,建议同时监听onpropertychange(仅 IE)或用input事件委托兜底
复杂校验场景下 validity 对象要手动判断
如果同时用了 required、pattern、min 等多个约束,oninvalid 触发时你得知道具体哪条失败,才能给出精准提示。
这时不能无脑 setCustomValidity('格式错误'),而应检查 input.validity 的各布尔属性:
-
input.validity.valueMissing→required未填 -
input.validity.patternMismatch→pattern不匹配 -
input.validity.rangeUnderflow→ 小于min -
input.validity.tooLong→ 超过maxlength
示例:
input.addEventListener('invalid', function(e) {
e.preventDefault();
if (this.validity.valueMissing) {
this.setCustomValidity('用户名不能为空');
} else if (this.validity.patternMismatch) {
this.setCustomValidity('用户名只能包含字母和数字');
} else {
this.setCustomValidity('');
}
});
注意 e.preventDefault() 可阻止原生提示弹出,但必须搭配 setCustomValidity 才真正生效。
真实项目里,validity 对象的状态组合很多,尤其涉及国际化时,提示文案要严格对应具体失效规则——漏判一种,就可能让用户反复提交失败却得不到明确指引。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











