html表单原生验证仅在submit时触发,依赖required、type、pattern,但需注意生效条件与常见陷阱;应配合checkvalidity()、reportvalidity()、setcustomvalidity()及:valid/:invalid等实现精准控制。

HTML 表单原生验证靠 required、type 和 pattern 就够用,但得知道它们什么时候生效、什么时候失效
浏览器内置验证不是“一设就灵”,它只在表单提交(submit 事件)时触发,且仅对用户手动输入后未修正的字段起作用。比如用户填了非法邮箱但没点提交,验证消息不会弹;又或者用 JS 直接给 input.value 赋值,required 也不会自动校验——它不监听 value 变化。
常见错误现象:input[type="email"] 允许填 foo@bar(缺域名后缀)也能通过验证;pattern 正则没加 ^$ 锚定,导致 pattern="[0-9]" 会误判 "abc123def" 合法。
-
required只检查是否为空字符串或未选中(select、checkbox),不校验内容格式 -
type="number"允许粘贴字母、显示空值却仍算“有效”,实际应配合min/max或 JS 补充判断 -
pattern必须匹配整个输入值,建议写成pattern="^[a-z]{3,}$"而非pattern="[a-z]{3,}"
用 checkValidity() 和 reportValidity() 主动控制验证时机
想在用户离开字段(blur)或按键(input)时立刻反馈?不能只靠原生行为。必须调用 DOM 方法:checkValidity() 返回布尔值,不显示提示;reportValidity() 才会触发浏览器默认气泡提示。
使用场景:搜索框实时校验手机号、注册页逐项提示。注意 reportValidity() 在 Firefox 中可能不滚动到错误字段,而 Chrome 会。
立即学习“前端免费学习笔记(深入)”;
- 对单个
input调用,如document.querySelector('#phone').reportValidity() - 对整个
form调用,如form.reportValidity(),会校验所有带约束的子元素 - 若需自定义提示文案,得先
setCustomValidity('错误信息'),再调reportValidity();清空提示用setCustomValidity('')
禁用原生验证时,novalidate 属性必须加在 form 标签上,而不是 button 或 input
很多人以为给提交按钮加 novalidate 就能关掉验证,其实无效。这个属性只对 form 元素生效,且作用是彻底禁用所有原生约束检查——包括 required、type、pattern 等。
性能影响:禁用后可避免部分低端安卓 WebView 的验证气泡卡顿,但也意味着你要 100% 自己实现逻辑,包括空值、格式、异步唯一性校验(如用户名是否已存在)。
- 正确写法:
<form novalidate></form> - 错误写法:
<button novalidate></button>或<input novalidate> - 兼容性:所有现代浏览器支持,IE10+ 也支持
novalidate
自定义验证常漏掉 :valid/:invalid CSS 伪类和 validity 对象细节
样式反馈和 JS 判断依赖同一个底层状态,但很多人只改样式或只写 JS,两边不同步。比如 CSS 里用 input:invalid { border-color: red; },但 JS 里却用 input.value === '' 判断是否为空——这会导致用户删掉内容后,样式变红,但 JS 认为“还没输,不算错”,体验割裂。
容易被忽略的地方:input.validity 是个对象,含 valueMissing、typeMismatch、patternMismatch 等布尔字段,比单纯看 checkValidity() 返回值更精准。
-
input.validity.valid是最终综合结果,等价于checkValidity() -
input.validity.valueMissing专指required未填,比input.value === ''更可靠(比如select的 placeholder option) - CSS 中
:user-invalid比:invalid更克制——只在用户交互后才触发样式,避免初始加载就红边框
pattern 写起来绕,且无法动态提示缺哪项;又比如邮箱需要后台确认是否真实存在,这时候原生验证连入场券都拿不到。











