原生校验需按浏览器硬编码顺序触发:valuemissing→typemismatch→patternmismatch;空值时pattern不执行,须trim后确保非空且正则含^$锚定;type="number"/"date"忽略pattern;实时反馈需手动监听+setcustomvalidity+reportvalidity。

原生校验不是加了属性就自动全程生效,它只在特定时机、特定结构下才触发;required 和 pattern 不能叠加判断空值与格式,type="number" 或 type="date" 上写 pattern 直接无效。
required 和 pattern 为什么总不一起生效
浏览器校验顺序是硬编码的:valueMissing → typeMismatch → patternMismatch。只要输入为空(input.value === ''),后续所有规则包括 pattern 都跳过执行。
- 用户没输内容就点提交 → 只看到“请填写此字段”,不会提示“手机号格式错误”
-
pattern必须配合非空输入才有机会触发,所以空格、制表符、全角空格等“看似有内容实则无效”的值也要提前 trim - 想让
pattern起作用,得确保字段已交互过且value不为空字符串(可用input.value.trim() !== ''判断)
pattern 正则必须显式写 ^ 和 $
浏览器对 pattern 的匹配逻辑是“整个字符串必须完全匹配”,但正则引擎默认不锚定——pattern="[0-9]{11}" 实际等价于 /[0-9]{11}/,会误判 "abc12345678901def" 合法。
- 正确写法是
pattern="^1[3-9]\d{9}$"或pattern="^[a-z0-9._%+-]+@[a-z0-9.-]+\.[a-z]{2,}$" -
title属性只影响气泡提示文案,不参与匹配逻辑;它不会自动补全或修正正则 -
pattern仅对type="text"、"email"、"tel"、"password"等文本类类型有效,type="number"和type="date"完全忽略该属性
type="date" 和 type="email" 的校验有多松
别指望 type="email" 拦住 user@localhost,也别信 type="date" 能拒绝 "9999-99-99" —— 浏览器只做最低限度解析,合法格式 ≠ 业务有效值。
-
type="email"只要求含一个 @ 和一个点号(如a@b.c)就通过,不校验域名是否存在 -
type="date"只认YYYY-MM-DD格式,但"2026-02-30"或"9999-99-99"在部分浏览器中仍返回validity.valid === true - 移动端 iOS Safari 的日期面板语言强制跟随系统,无法用
lang或accept-language切换,原生提示永远是系统语言
如何让校验真正“实时”反馈
原生验证默认只在 submit 时触发,想做到输入即提示,必须手动接管:监听事件 + setCustomValidity + reportValidity,且每次都要清空旧状态。
- 监听
input(适合密码强度、手机号格式)或blur(适合确认密码、离开后校验) - 每次触发前先调
input.setCustomValidity(""),否则旧错误残留,用户改对了也弹错提示 - 校验失败时设
input.setCustomValidity("请输入合法日期"),再立即调input.reportValidity()弹出气泡 -
form.requestSubmit()是唯一能替代form.submit()并保留验证链的方法,但 IE 和旧安卓 WebView 不支持,需 fallback 到form.checkValidity()+ 手动提示
最常被忽略的是状态重置时机:哪怕只是多输一个空格,setCustomValidity("") 没被调用,后续所有 reportValidity() 都会重复显示上一次的错误文案。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











