required 属性仅在语义化 内、type 有效的可提交控件(如 text、email、select)且含 name 属性时生效;脱离 form、按钮非 type="submit"、手动调用 form.submit()、动态渲染未同步 required 状态等均导致校验失效。

表单没包在 <form></form> 里就加 required
浏览器只认语义化表单结构,required 必须依附于 <form></form> 才能触发校验。单独把 <input required> 放在 <div> 或页面任意位置,它只是个带布尔属性的标签,完全不参与验证。
<p>常见翻车点:</p>
<ul>
<li>
<code><input name="email" required> 却没被 <form></form> 包裹 → 校验静默失效
input 后直接 append 到 body,忘了先创建 form 容器 → 表单未连接(form.isConnected === false)input 跑到了 form 外层 → 属性存在但无效
submit 按钮不是 type="submit" 或被 preventDefault() 拦截了
required 只在原生提交行为中触发:点击 <button type="submit"></button>、<input type="submit">,或在表单内按回车。其他方式一律绕过校验。
排查要点:
- 按钮写成
<button></button>或<button type="button"></button>→ 浏览器根本不当它是提交控件 - JS 里监听
submit事件却写了e.preventDefault(),又没调form.checkValidity()→ 校验被拦腰截断,无提示也无报错 - 用
form.submit()手动提交 → 原生校验完全不执行,这是规范行为,不是 bug
元素类型或属性缺失导致浏览器直接跳过校验
required 仅对特定可提交控件生效,且依赖几个隐含前提。写错了类型或漏了关键属性,等于白加。
必须检查:
- 是否用了不支持的类型:如
<input type="hidden">、<input type="button">、<div> → 浏览器忽略 <code>required属性 -
input或select是否有name属性 → 没name的字段不会被纳入校验范围 -
<select required></select>是否有默认空选项:<option value="" disabled selected>请选择</option>→ 否则首个option被自动选中,required形同虚设 - 动态渲染的字段(如 Vue
v-if、React 条件渲染)是否在 DOM 插入后再设置required→ 提前设属性,DOM 还没挂载,属性不被解析 - 单选按钮中选 “其他”,JS 显示关联文本框并设
input.required = true - 用户没选 “其他”,该文本框仍在 DOM 中、
required为 true → 提交时因为空值被拦截,且无任何提示
动态添加 required 但元素仍存在于 DOM 中(即使隐藏)
只要元素在 DOM 树里且带 required,浏览器就会校验它,不管它是不是 display: none 或 visibility: hidden。这是最容易被忽略的静默失败点。
典型场景:
修复逻辑必须严格同步:元素不可见时,必须同时移除 required 或设 required = false;可见时才加回。不能只靠 CSS 控制显示/隐藏。











