checkvalidity()仅校验html5内置约束(required、type、min/max、pattern等),不执行自定义逻辑;需配对type与pattern、确保渲染完成、结合reportvalidity()反馈或setcustomvalidity()联动事件,并用touched状态避免误标。

用 checkValidity() 前先搞清它到底校什么
checkValidity() 只检查 HTML5 内置约束(required、type="email"、min/max、pattern 等),不触发自定义逻辑,也不管字段是否“业务上合理”。比如一个 required 的手机号输入框,即使用户填了 "abc",只要没清空,checkValidity() 就可能返回 true(因为 type="text" 下 "abc" 是合法字符串)。
实操建议:
- 确认所有输入控件都设置了匹配语义的
type(如邮箱用type="email",数字用type="number"),否则内置校验形同虚设 - 对
type="text"且需格式校验的字段,必须配pattern属性(例如手机号:pattern="^1[3-9]\d{9}$"),不然checkValidity()不会校正则 - 调用前确保元素已渲染完成(避免在 Vue/React 的
mounted或useEffect之外过早调用)
手动触发校验时别漏掉 reportValidity()
reportValidity() 不仅执行校验,还会在不通过时自动显示浏览器默认提示气泡(含定位和样式),而 checkValidity() 只返回布尔值。很多开发者只用后者,结果校验逻辑写了,用户却看不到任何反馈。
实操建议:
- 表单提交时优先用
reportValidity(),它兼容性好(Chrome 41+、Firefox 40+、Safari 10.1+),且省去手写提示逻辑 - 若需统一 UI 风格(比如弹窗或行内红字),可先调
checkValidity()判断,再手动控制提示;但此时必须遍历所有elements,读取每个元素的validationMessage属性获取具体错误文本 - 注意:Safari 对
reportValidity()的气泡定位偶有偏移,可在:valid/:invalidCSS 中加outline: none避免双轮廓干扰
自定义校验要靠 setCustomValidity() + 事件联动
业务规则(如“两次输入密码必须一致”“用户名不能包含敏感词”)无法靠 HTML 属性表达,必须用 JS。核心是:每次值变化后重置并设置新的校验状态,否则旧错误会残留。
实操建议:
- 在
input或blur事件中调用setCustomValidity("")清空旧状态,再根据逻辑决定是否设错误信息(如password2.setCustomValidity(password2.value !== password1.value ? "两次输入不一致" : "")) - 不要在
submit事件里集中设 custom validity——那样用户得不到实时反馈,体验断层 - 设空字符串
""表示“通过”,设非空字符串表示“失败”;设" "(空格)会被当成错误,这点容易踩坑
校验状态同步到 UI 时避开 class 切换陷阱
很多人用 element.classList.toggle("error", !element.checkValidity()),但这是错的:它只反映当前值是否满足约束,却忽略用户是否已与该字段交互过(比如刚打开页面,所有字段都为空,required 字段本该是 invalid,但用户还没点过,不该立刻标红)。
实操建议:
- 引入“touched”状态:监听
focusout设置data-touched="true",再结合checkValidity()决定是否加 error class - CSS 中用
[data-touched][aria-invalid="true"]而不是单纯.error控制样式,确保只对用户操作过的字段高亮 - 避免直接操作
className,改用classList.add()/remove(),防止覆盖其他动态 class(如框架注入的)
最易被忽略的一点:校验逻辑分散在多个事件里(input、blur、submit),但它们共享同一套 DOM 状态。一旦某个环节忘记重置 setCustomValidity(""),后续校验就会被滞留的错误卡住——这种问题往往在线上才暴露,且难以复现。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











