required属性生效需同时满足四个条件:①控件必须被完整<form>包裹;②提交必须触发原生submit事件;③仅<input>(非hidden/button等)、<select>、<textarea>支持;④空值判定仅认value="",不认空格。

直接用 required 属性最简单,但光加这个属性经常失效——不是写法错,而是缺了关键上下文或踩了浏览器行为的坑。
required 属性生效的四个硬性条件
它不是“写了就校验”,必须同时满足:
-
<form>标签完整包裹所有带required的控件;缺一层外层<form>,整个验证链就断了 - 提交动作必须触发原生
submit事件:按钮得是<button type="submit">或<input type="submit">;type="button"或 JS 调用form.submit()都绕过校验 - 目标元素类型必须支持:仅
<input>(排除type="hidden"、"button"等)、<select>、<textarea>;自定义组件或div[contenteditable]加了也无效 - 空值判定只看 DOM 的
value属性:" "(空格)算已填,""(空字符串)才算空;<select>的默认项若写成<option value="">请选择</option>却没加disabled,用户没动它,就会一直卡在校验失败
为什么加了 required 却没拦住提交
常见静默提交,根本原因是校验被意外关闭或未触发:
- 在
submit事件里写了e.preventDefault(),却没紧接着调form.checkValidity()——等于主动关掉浏览器校验开关 - 用了
<button onclick="handleSubmit()">,没设type="submit",浏览器压根不启动验证流程 - 移动端 WebView(比如旧版微信内置浏览器)直接忽略
required,checkValidity()都返回true,必须额外做降级检测,比如手动判断input.value.trim() === ""
让提示更友好:从失焦开始反馈
原生 required 只在提交时弹气泡,用户体验差。想失焦即提示,得手动干预:
文章转信息图。将文章/笔记转化为手机可读的 HTML 信息图,自动匹配视觉风格。触发场景:文章转图、笔记转图、信息图、转小红书图、做张图、可视化这篇文章、文生图。
立即学习“前端免费学习笔记(深入)”;
- 监听
blur事件,对目标input调用input.reportValidity()——它会触发原生气泡,且返回布尔值供你判断是否通过 - 避免在
input事件里反复调setCustomValidity(),容易让浏览器内部validity状态混乱;清空错误必须显式调input.setCustomValidity("") - 视觉反馈别只靠
:invalid伪类一加载就生效,否则页面刚打开所有必填框全变红;可用input:invalid:not(:placeholder-shown)组合控制,前提是写了placeholder
动态必填字段怎么实现
required 是静态属性,无法响应其他字段状态变化。要实现“填了 A 才要求填 B”,必须用 JS 动态操作:
- 监听 A 字段的
input或change事件 - 根据 A 的值(如
A.value.trim() !== "")决定是否给 B 添加required属性:B.required = true或B.removeAttribute("required") - 注意同步调用
B.checkValidity()或触发布局重排,否则浏览器可能不立即更新校验状态 - 别忘了服务端仍需二次校验——前端动态加的
required完全可被禁用或绕过
最容易被忽略的是:移动端兼容性和服务端兜底。哪怕 required 在 Chrome 里跑得飞起,微信 WebView 里可能直接静默放行;而任何前端校验,包括 JS 动态逻辑,都只是第一道过滤网,后端不校验等于没校验。


















