required属性仅对具有空值语义的原生表单控件生效,如text、email、checkbox等;需确保通过原生submit触发、form存在、字段未disabled,且服务端必须二次校验。

直接加 required 属性就行,但加错位置、选错元素类型或忽略触发条件,它就形同虚设。
哪些元素能用 required?
只对有明确“空值语义”的原生表单控件生效:
-
input类型必须是text、email、number、tel、url、date、checkbox、radio、file -
select(但必须配<option value="">请选择</option>,且不能加selected) textarea
以下写了也无效:input type="hidden"、input type="button"、input type="range"、input type="color"、div、自定义组件(如 <my-input>)。
required 不触发校验的常见原因
不是属性没写对,而是提交动作没走浏览器原生路径:
立即学习“前端免费学习笔记(深入)”;
- 用了
<button type="button">或没写type属性(默认是button),不是submit - 表单外点击按钮,或用 JS 执行
form.submit()—— 这个调用完全跳过校验 - 在
submit事件里写了event.preventDefault(),但没手动调form.checkValidity()或form.reportValidity() -
form标签缺失,或被 JS 动态移除 - 字段被设为
disabled(直接跳过校验),而readonly仍参与校验
移动端尤其注意:旧版 iOS Safari(≤15.4)对 select 和 file 的 required 支持不稳定,建议加 JS 降级判断。
动态控制必填状态:JS 操作 required 属性
用 JS 切换是否必填,别用 setAttribute,直接操作 DOM 属性更可靠:
const field = document.getElementById('comments');
const trigger = document.getElementById('needComments');
trigger.addEventListener('change', () => {
if (trigger.value === 'reject') {
field.required = true;
} else {
field.required = false;
}
});
注意点:
- 不要写
field.setAttribute('required', 'required'),容易和布尔逻辑混淆 - 受控组件(如 React 中的
value由 state 控制)需确保初始value是'',否则首次渲染就触发:invalid - 修改后不会自动重校验,想立刻反馈提示,得调
field.reportValidity()
服务端必须二次校验,别信前端
required 只防手滑,不防绕过。curl、禁用 JS、删 HTML 属性、填空格 " " 都能绕过。
后端要检查:
- 字段是否存在(HTTP body 里根本没这个 key)
- 值是否为
null、undefined、空字符串""、纯空白"\t\n " - 对
checkbox或radio,确认是否收到对应 name 的值(没勾选时通常不传)
最易被忽略的是:前后端对“空”的定义不一致。比如手机号字段,前端认为 "123" 是空,后端却只判 == null —— 这种错位会导致数据污染,且难以排查。



















