HTML解析引擎仅构建DOM树,表单验证由浏览器约束验证子系统动态执行;提交时遍历控件检查required(trim后为空)和pattern(隐式^$锚点),失败则阻止提交并提示;禁用JS仍生效;setCustomValidity设customError状态并覆盖验证结果。

HTML解析引擎本身不“解析表单验证”——它只负责把HTML标记转成DOM树,而表单验证逻辑由浏览器的**表单约束验证子系统**(Constraint Validation API 实现层)在渲染后动态执行。
浏览器怎么触发 required 和 pattern 校验
当用户点击 <input type="submit"> 或调用 form.submit() 时,浏览器会同步执行以下动作:
- 遍历所有表单控件,检查是否设置了
required属性且值为空(注意:value.trim() === ""才算空,空格不算) - 对设置了
pattern的字段,用其正则字符串构造RegExp对象(隐式启用^和$锚点),再调用test(input.value) - 若任一控件校验失败,阻止提交,并调用内部
reportValidity()显示默认气泡提示 - 这个过程不依赖 JavaScript 是否启用——禁用 JS 后,
required和pattern依然生效
setCustomValidity() 怎么覆盖原生验证
该方法本质是修改 DOM 元素的 validity.customError 状态位,并设置 validationMessage。一旦你调用了 element.setCustomValidity("错误信息"),哪怕输入内容完全合法,element.checkValidity() 也会返回 false,直到你传入空字符串重置:
const pwd = document.querySelector('#password');
pwd.addEventListener('input', () => {
if (pwd.value.length < 8) {
pwd.setCustomValidity('密码至少8位');
} else if (!/[A-Z]/.test(pwd.value)) {
pwd.setCustomValidity('需包含大写字母');
} else {
pwd.setCustomValidity(''); // 必须清空,否则永远 invalid
}
});
常见坑:忘记清空、在非 input 事件里调用(比如只在 submit 里设,但用户没点提交就离开页面)、与 required 冲突导致提示被覆盖。
立即学习“前端免费学习笔记(深入)”;
为什么 pattern 对空值不校验
这是 HTML5 规范明确规定的:只有当字段有值时,pattern 才参与匹配。所以如果你写:
<input type="text" pattern="[a-z]{3}">
用户留空也能通过验证。真正要“非空且符合格式”,必须显式加 required:
<input type="text" pattern="[a-z]{3}" required>
否则会出现“允许空、但填了就必须是三个小写字母”的语义,和业务预期不符。很多开发者卡在这里,以为 pattern 自带必填逻辑。
移动端 pattern 正则的兼容性陷阱
iOS Safari 和 Android Chrome 对 pattern 的正则引擎支持不一致:
-
pattern="[\u4e00-\u9fa5]+"(中文)在 iOS 上可能被忽略,或触发键盘异常 - 使用
\d在部分安卓 WebView 中等价于[0-9],但某些旧内核不识别 Unicode 类别 - 推荐写法:用
[0-9]替代\d,中文用[\u4e00-\u9fa5]并加title提示,同时在 JS 中 fallback 双重校验
最易被忽略的一点:浏览器对 pattern 的编译发生在首次渲染或属性变更时,而不是每次输入——所以动态改 pattern 属性后,必须手动调用 input.reportValidity() 才能立即生效。



















