required仅在submit时触发校验,非实时验证;只作用于语义化表单控件(如input、select、textarea等),依赖value属性判空,需手动调reportValidity()实现失焦提示。

required 为什么只在 submit 时才弹气泡
它根本不是“实时校验器”,而是浏览器在 submit 事件触发前做的一个同步拦截检查。只要没走到这一步,required 就是静默的——不监听 input、不响应 blur、也不管你 JS 改了什么值。
常见误判场景:
- 用
button onclick="handleSubmit()",没设type="submit"→ 浏览器压根不启动校验流程 - 写了
form.addEventListener('submit', e => e.preventDefault())却没跟form.reportValidity()→ 主动关掉校验开关,还指望气泡出来 - 调用
form.submit()方法 → 这是纯 JS 提交,绕过所有原生验证 -
form标签被漏写,或控件没包进form里 → 属性存在,但无上下文,浏览器直接忽略
哪些元素加 required 才真生效
不是所有带交互的标签都能响应 required,它只认语义化表单控件,且对类型有硬性限制:
- ✅ 有效:
input(排除type="hidden"、"button"、"submit"、"reset")、select、textarea、input[type="checkbox"]、input[type="radio"]、input[type="file"] - ❌ 无效:
div[contenteditable]、自定义组件、input[type="range"](无空值语义)、input[type="color"] - ⚠️ select 特别容易翻车:
<option value="">请选择</option>必须加disabled selected,否则默认选中它就立刻报错
空值判定到底看什么
浏览器不看你输没输、光标停在哪、placeholder 显示什么,它只读 DOM 的 value 属性(或 select 当前选中项的 value):
立即学习“前端免费学习笔记(深入)”;
-
" "(纯空格)、"\t"、"\u200B"(零宽字符)→.value.trim() === ""为真,算空,required拦住 -
input[type="number"]输入字母后,value变成""(不是"NaN"),仍被required判为空 -
textarea里换行符\n算内容,但"\n\n"+.trim()后是""→ 仍失败 -
input[type="checkbox"]没勾选 →checked === false,required视为未填
想失焦就提示?得手动调 reportValidity()
:invalid 伪类一加载就生效,会导致页面打开所有必填框全红;而原生气泡只在 submit 时出现。若要失焦即反馈,必须靠 JS 干预:
- 监听
blur,然后调input.reportValidity()—— 它会聚焦该字段、弹气泡、返回布尔值 - 别用
checkValidity()替代:它只返回true/false,不触发 UI - 别在
input事件里反复调setCustomValidity():容易让 validity 状态卡死,清空必须显式调input.setCustomValidity("") - 动态插入的控件(如 JS 创建后
appendChild),required属性得等节点挂载到document后再设,否则不被解析
最常被忽略的一点:required 的作用域窄得惊人——它只回答“空不空”,不碰“对不对”;只活在 submit 那一瞬间,其余时间连影子都没有。想让它干更多事,就得补 JS,而不是反复检查属性有没有拼错。



















