原生校验能覆盖80%基础场景,但仅用required和type="email"易在移动端、无障碍及提示一致性上出问题;pattern需配合type="text"/"email"等文本类型、显式锚定且避免与required冲突才生效。

原生校验能覆盖 80% 以上的基础场景,但直接写 required 和 type="email" 就交差,大概率会在移动端、无障碍、错误提示一致性上翻车。
为什么 pattern 写对了却没生效?
常见现象:正则看起来没问题,但输入合法内容仍报错,或根本没触发校验。
-
pattern只在字段有值时才参与校验;如果同时加了required,空值会先被required拦住,pattern压根不运行 - 正则默认是“全匹配”,不是“包含”。比如想校验邮箱后缀为
@example.com,写pattern="@example\.com$"是错的,必须写pattern="^[^\s@]+@example\.com$" - 移动端 Safari 对某些 Unicode 字符(如中文邮箱用户名)的
pattern支持不稳定,建议用type="text"+ JS 补位,而非强依赖 -
title属性值会作为默认错误提示显示,但仅当pattern不匹配且无自定义消息时才 fallback 使用,别指望它替代setCustomValidity()
checkValidity() 和 reportValidity() 到底该用哪个?
两者都返回布尔值,但行为差异直接影响用户感知。
-
checkValidity()只做判断,不触发 UI 提示。适合在提交前静默检查,或配合自定义错误展示逻辑 -
reportValidity()除了返回结果,还会强制浏览器显示原生气泡提示(含validationMessage),适用于“点击按钮就立刻反馈”的场景 - 注意:调用
reportValidity()后,若字段本身未聚焦,气泡可能出现在页面顶部或不可见区域——这不是 bug,是浏览器实现。如需精准定位提示,得自己实现 DOM 级错误容器 - 在表单
submit事件里,直接return form.checkValidity()即可,无需preventDefault();浏览器会自动阻止提交并显示提示
怎么让 :valid/:invalid 伪类真正可控?
CSS 伪类看似方便,但默认行为容易和业务状态冲突。
-
:invalid在用户还没输任何内容时就可能命中(比如required字段初始为空),导致一进页面就红边框,体验极差 - 推荐做法:给表单加一个
data-touched="false"属性,JS 在input或blur时设为true,CSS 写成form[data-touched="true"] input:invalid,避免初始误判 -
:user-invalid是更精确的伪类(Chrome 107+、Firefox 110+ 支持),只在用户交互后且验证失败时触发,但兼容性仍需兜底 - 不要只靠伪类改边框色——屏幕阅读器不会读取 border-color。必须配合
aria-invalid="true"和aria-describedby指向错误文案
最常被忽略的一点:原生校验的 validationMessage 是只读的,且不同浏览器返回的文案风格差异极大(比如 Chrome 说“Please match the requested format”,Safari 说“Value must match the pattern”)。如果你的产品要求中文化、品牌化提示,就必须用 setCustomValidity() 覆盖,而且得在每次 input 时清空再重设,否则旧错误会残留。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











