formnovalidate仅对type="submit"按钮生效,用于跳过原生校验但不影响js校验、伪类及服务端校验,需配合form属性绑定外部按钮,不可替代后端容错。

formnovalidate 必须配合 type="submit" 才生效
它不是万能开关,只对真正会触发表单提交的按钮起作用。常见错误是写成 <button formnovalidate></button>,但没声明 type —— 此时浏览器默认为 type="button",根本不提交,formnovalidate 就成了摆设。
正确写法只有两种:
<button type="submit" formnovalidate>保存草稿</button><input type="submit" formnovalidate value="保存草稿">
如果按钮不在 <form></form> 标签内部,必须用 form 属性显式绑定表单 ID,否则静默失效:<button type="submit" form="myForm" formnovalidate></button>。
formnovalidate 不等于“关掉校验”,只是跳过当前提交
它只影响点击该按钮时的原生校验行为(比如 required、type="email" 弹窗),不影响以下任何一项:
- JavaScript 调用
form.checkValidity()或form.reportValidity()仍会返回真实结果 - 字段的
:valid/:invalid伪类照常响应输入状态 -
form.submit()方法调用仍会触发完整校验(绕过formnovalidate) - 服务端完全收不到这个属性,后端不做校验就可能存入空数据
所以“暂存草稿”逻辑里,前端跳过校验是方便用户,但后端必须做最小字段容错判断(比如允许 email 为空,但 user_id 不能丢)。
别和 novalidate 混用,优先选 formnovalidate 做细粒度控制
如果整个 <form novalidate></form>,那所有提交按钮都跳过校验,容易漏掉“正式提交”时的关键检查。而 formnovalidate 是按钮级开关,更安全:
- 一个表单里可以同时存在
<button type="submit">正式提交</button>(走原生校验)和<button type="submit" formnovalidate>暂存草稿</button>(跳过) - 两者互不干扰,也不需要 JS 监听 submit 事件再
preventDefault() - 即使 JS 未加载或执行失败,
formnovalidate依然生效,适合 SSR 页面
唯一要注意的是:多个按钮都加了 formnovalidate,就等于整个表单暂时失去客户端防护,得靠后端兜底。
formnovalidate 无法绕过 JavaScript 主动校验
如果你在 submit 事件里手动调用了 checkValidity() 或 reportValidity(),formnovalidate 对这部分逻辑完全无效。它只屏蔽浏览器原生提交拦截。
典型踩坑场景:
- 用了
form.requestSubmit()—— 这个方法会强制触发校验,哪怕按钮带formnovalidate - 监听了
submit事件,又在回调里调用this.form.checkValidity(),结果还是弹出错误提示
稳妥做法是:如果业务强依赖“无校验提交”,要么改用 event.preventDefault(); this.form.submit();,要么干脆把校验逻辑全交给 JS 控制,统一用 <form novalidate></form> + 手动触发。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











