required仅在原生表单submit事件触发时校验,依赖value值(trim后为空才报错),失效原因包括:未嵌套form、按钮非submit类型、不支持的input类型、同名多字段及WebView兼容性问题。

required 属性本身不主动校验,只在原生表单提交(submit 事件)那一刻由浏览器统一检查;它不监听输入、不响应 form.submit() 调用,也不管你输的是空格还是乱码。
required 校验触发的唯一时机是原生 submit
浏览器只在以下两种情况执行 required 检查:
- 用户点击
<button type="submit">或<input type="submit"> - 用户在可提交表单内按回车(且焦点不在
textarea等多行控件上)
除此之外,全都不触发——包括:input.addEventListener('input', ...)、blur、form.submit()(JS 调用会跳过验证)、fetch() 提交、禁用 JS 后手动改 DOM……这些场景下 required 形同虚设。常见错误是加了 required 却在 submit 里写了 event.preventDefault(),又没手动调 form.checkValidity(),结果校验被静默绕过。
required 怎么判断“没填”?只看 value,不看 placeholder
校验逻辑非常机械,完全依赖 DOM 的 value 属性值:
立即学习“前端免费学习笔记(深入)”;
-
<input required>:等价于input.value.trim() === "";" "(纯空格)算已填写,""才算空 -
<select required>:检查select.selectedIndex === 0且首个<option>的value为空字符串或未定义(所以必须写<option value="" disabled selected>请选择</option>) -
<textarea required>:同样只读textarea.value,哪怕里面显示文字但 JS 清空了value,就立刻变无效
注意:placeholder、label、innerText 全部不参与判断;disabled 的字段直接被跳过校验(哪怕带 required);readonly 的仍参与。
将调研报告、方案对比、数据分析、需求梳理、会议纪要、设计说明、代码评审、学习笔记等任务产物输出为可在浏览器直接打开的单文件 HTML,替代 Markdown 作为最终交付物。Markdown 在信息密度、视觉清晰度和可分享性上已跟不上 AI 产物的丰富度,HTML 能同时承载排版、表格、SVG 等。
required 失效的四个典型原因
遇到“加了 required 却没拦住提交”,先查这四点:
- 表单元素没包在
<form></form>内——required必须依附语义化表单结构才能被识别 - 提交按钮是
<button type="button">或没写type(默认为button),不是submit -
input类型不支持 required:type="hidden"、"button"、"submit"、"reset"、"image"都无效 - 同名字段多个(如两个
name="email"),浏览器只校验第一个,后面被忽略
移动端 WebView(如旧版微信)可能完全忽略 required,需额外用 JS 补充 checkValidity() 判断。
想自定义提示?setCustomValidity() 必须配对清空
浏览器默认提示不可删改,只能覆盖。唯一办法是调 setCustomValidity():
- 传非空字符串(如
input.setCustomValidity("用户名不能为空"))→ 触发失败状态并显示该文案 - 传空字符串(
input.setCustomValidity(""))→ 显式标记为通过;传null无效
关键陷阱:这个状态是“粘性”的。一旦设错,后续即使用户输进合法内容,只要没调 setCustomValidity(""),就永远报错。正确做法是在 blur 或 input 事件里做判断:
const input = document.querySelector('input[required]');
input.addEventListener('blur', () => {
if (!input.value.trim()) {
input.setCustomValidity('此项不能为空,且不能只填空格');
} else {
input.setCustomValidity(''); // 必须清空!
}
});
最后强调一点:required 只管“空不空”,不管“对不对”。邮箱格式、手机号长度、密码强度……这些都得靠 type、pattern、minlength 或 JS 补充,而且服务端永远要二次校验——前端任何校验都可被绕过。


















