问题的关键在于,浏览器会将

select required 为什么首项 value="" 却不报错
根本原因是:浏览器会把 当成“已选择的有效值”,即使它本质上只是一个提示占位项。只要这个空值 option 没有被禁用,required 就会判断用户已经完成选择,因此表单校验会直接通过。
常见表现包括:点击提交表单后没有任何提示、控制台也没有报错、页面看似正常跳转,但实际上后端收到的却是空字符串 ""。这也是很多人在处理 HTML select 必填校验时最容易踩到的坑。
- 不要只写
,正确做法是必须同时加上disabled和selected disabled用来阻止该项参与提交,selected用来作为默认显示的提示项,两者缺一不可- 其他可选项的
value必须设置为非空字符串(如"active"、"1"),否则依然可能导致required校验被绕过
正确的 select required 写法示例
下面这种写法,才能让 select required 真正触发必填拦截:
关键点如下:
disabled是最核心的属性,它会让提示项不参与表单数据提交selected可以保证页面加载时默认停留在提示项上,用户必须手动切换到其他选项才算有效选择- 如果去掉
disabled,即使保留了required,首项仍然会被当成有效值,提交时照样不会报错
submit 事件里 preventDefault 后 required 失效怎么办
如果你在表单的 submit 事件中调用了 e.preventDefault(),但没有继续执行 form.checkValidity(),本质上就是手动关闭了浏览器原生校验。这种情况下,select 上的 required 自然不会生效。
- 监听
submit事件时,应先调用form.checkValidity()判断表单是否通过验证 - 当返回
false时,浏览器通常会自动聚焦到第一个校验失败的字段,并弹出原生提示,无需你再额外处理 - 只有在返回
true时,才继续执行后续逻辑,比如 Ajax 请求或其他提交操作 - 不要使用
这种方式,按钮必须设置为type="submit",否则连标准的submit事件都不会正常触发
reportValidity() 在 select 上的兼容性坑
如果你想手动触发表单校验,比如在失焦时调用 select.reportValidity(),思路本身没有问题,但不同浏览器的实际表现并不完全一致。尤其是在 Firefox 中,它对空 value 的处理通常比 Chrome 更严格:即使已经写了 disabled selected,某些场景下仍然可能直接提示错误。
- 更稳妥的做法是:只在
submit事件中依赖浏览器原生校验行为,尽量避免手动调用reportValidity() - 如果必须手动校验,可以改用
form.checkValidity(),再结合遍历form.elements检查validity.valueMissing - 还要注意,旧版本 iOS Safari 对
select[required]的支持并不稳定,因此加上disabled selected仍然是最可靠、兼容性最好的解决方案
很多人真正忽略的地方就在这里:disabled 不是可有可无的辅助属性,而是 select required 必填校验能否生效的关键。少了它,required 在 select 标签上的作用基本等于失效。
