原生 required 属性仅触发浏览器默认提示且不可定制;需用 checkvalidity() 判断、reportvalidity() 触发提示;:valid/:invalid 可做样式反馈但需避初始误标;setcustomvalidity() 支持自定义文案并配合 dom 渲染错误信息。

HTML 原生 required 属性只校验不提示
直接加 required 到 <input> 或 <select></select> 上,提交时浏览器会阻止表单发送,并弹出默认提示(如“请填写此字段”),但这个提示不可定制、不可捕获、也不在 DOM 中渲染——它由浏览器 UI 层控制,无法用 CSS 修改样式,也无法监听触发时机。
如果你需要自定义文案、位置、动画或和业务逻辑联动(比如聚焦到错误字段、上报埋点),就不能只依赖原生 required。
checkValidity() + reportValidity() 控制校验与提示时机
这两个方法是 HTML 表单验证 API 的核心。它们不改变表单状态,只触发校验逻辑和 UI 提示:
-
checkValidity()返回true或false,不显示任何提示 -
reportValidity()返回true或false,且在false时强制触发浏览器默认提示
常见用法是:在用户点击提交按钮时,先调用 form.checkValidity() 判断,再决定是否调用 reportValidity() 或走自定义提示逻辑:
document.querySelector('form').addEventListener('submit', e => {
e.preventDefault();
if (!e.target.checkValidity()) {
e.target.reportValidity(); // 触发原生提示
return;
}
// 继续提交逻辑
});
用 :valid / :invalid 伪类做实时视觉反馈
原生 required 字段在输入后会自动切换 :valid 和 :invalid 状态,无需 JS 就能响应式改变样式:
input:invalid:not(:placeholder-shown) {
border-color: #e53e3e;
}
input:valid {
border-color: #38a169;
}
注意两个关键点:
-
:invalid在字段为空时就为真,容易造成“一进页面就红”,加:not(:placeholder-shown)可避免初始误标(前提是用了placeholder) - 该伪类只响应原生约束(
required、type="email"、pattern等),不响应 JS 手动设置的setCustomValidity()
真正可控的提示:用 setCustomValidity() + 自定义 DOM 元素
如果必须完全接管提示逻辑(比如统一 tooltip、配合 FormItem 组件、支持多语言),就得绕过原生提示,手动控制:
- 对每个必填字段调用
input.setCustomValidity('')清空默认错误 - 校验失败时调用
input.setCustomValidity('此项为必填项') - 再调用
form.reportValidity()—— 此时浏览器仍会弹提示,但内容是你设的字符串 - 更彻底的做法是:只用
checkValidity(),自己遍历form.elements,读取input.validationMessage,然后插入<span class="error">...</span>到对应位置
这个路径灵活,但要注意:setCustomValidity('') 是重置的关键,漏掉会导致后续所有校验都返回 false。
required 是开关,reportValidity() 是扳机,而 setCustomValidity() 才是把提示权从浏览器手里拿回来的第一步。











