html原生required属性足够实现必填校验,无需js;仅作用于input/select/textarea,需在表单内且避免type="button"提交;自定义提示须用setcustomvalidity()动态控制;react/vue中需避免value为null/undefined导致误触发;后端必须重复校验,因required非安全机制。

HTML 原生 required 属性就足够了
直接在 <input> 标签上加 required 属性,浏览器会自动阻止表单提交,并聚焦到该输入框,同时显示默认提示(如 “请填写此字段”)。不需要 JS、不需要额外配置,这是最轻量、最可靠的必填校验起点。
常见错误是以为必须搭配 name 或 id 才能生效——其实只要标签合法、在表单内,required 就起作用。但注意:如果表单用 button type="button" 提交(绕过原生 submit 事件),required 会完全不触发。
-
<input type="text" required>✅ 有效 -
<input type="text" required="">✅ 等价写法 -
<input type="text" required="false">❌ 无效(布尔属性不认值) <div contenteditable required> ❌ 不支持,仅适用于可提交的表单控件(<code>input、select、textarea)如何自定义
required的错误提示文案浏览器默认提示无法通过 HTML 属性修改,必须用 JS 调用
setCustomValidity()干预。关键点在于:只要传入非空字符串,就会覆盖原生提示;传入空字符串,才恢复原生校验逻辑。典型误操作是只调一次
setCustomValidity('必填'),之后即使用户输入内容,校验状态仍卡在“无效”。必须配合input或blur事件动态清空:<input id="username" required><script> const el = document.getElementById('username'); el.addEventListener('input', () => { if (el.value.trim()) { el.setCustomValidity(''); // 恢复原生校验 } else { el.setCustomValidity('用户名不能为空'); } }); </script>React/Vue 中绑定
required要小心受控与非受控切换在 React 中,如果给
<input required value="{value}" onchange="{...}">加了required,但初始value是undefined或null,会导致首次渲染时元素被判定为“空值”,触发浏览器红框+焦点锁定——哪怕用户还没开始输入。根本原因是:受控组件的
value为null/undefined时,DOM 实际值为空字符串,而required正好校验这个空字符串。- ✅ 安全做法:初始化
value为''(空字符串) - ✅ 或改用非受控模式:
defaultValue+ref获取值 - ❌ 避免
value={null}或value={undefined}配合required - Vue 同理:
:value="null"也会触发相同问题
后端不能只信
required,但前端必须用它required是用户体验层的守门人,不是安全机制。它可能被禁用(开发者工具删掉属性)、绕过(直接 fetch 提交)、或在 JS 错误时彻底失效。所以后端必须重复校验,且不能依赖前端传来的“是否必填”元数据。但前端不用
required也不行:它提供无障碍支持(屏幕阅读器识别必填)、键盘导航兼容性(Tab 到必填项时有视觉反馈)、以及零 JS 降级体验。如果你为了“统一校验逻辑”而全用 JS 实现必填,反而会丢失这些基础能力。真正容易被忽略的是:当多个必填项并存时,浏览器只聚焦第一个未填项,不会高亮全部。如需全量提示,得自己监听
submit事件遍历验证——但别删掉required,它是底层支撑。- ✅ 安全做法:初始化











