required属性仅在原生submit事件中生效,需满足form包裹、submit按钮、支持元素类型、空值判定四条件;失焦提示、自定义文案、移动端兼容等均需js手动干预。

原生 required 属性能拦住空提交,但不会自动显示视觉提示、不处理空格、不响应失焦,更不能改提示文案——它只在点击 submit 时“硬拦”,其余都得你补。
required 属性生效的硬性前提
它不是写了就管用,必须同时满足四个条件:
-
<form></form>标签包裹所有带required的控件,缺一层外层form就彻底失效 - 提交动作必须触发原生
submit事件:按钮得是<button type="submit"></button>或<input type="submit">;type="button"或 JS 调用form.submit()都绕过校验 - 目标元素类型必须支持:
input(排除type="hidden"、"button"等)、select、textarea;自定义组件或div[contenteditable]加了也白加 - 值为空的判定只看 DOM 的
value属性:" "(空格)算已填,""(空字符串)才算空;select的首个<option value=""></option>若没加disabled,选中它照样报错
为什么加了 required 却没弹提示
常见现象是表单静默提交成功,根本没拦。原因往往不是属性写错,而是:
- 你在
submit事件里写了e.preventDefault(),却没紧接着调form.checkValidity()—— 这等于主动关掉了浏览器校验开关 - 用了
<button onclick="handleSubmit()"></button>,没设type="submit",浏览器压根不启动验证流程 -
select的默认项写成<option value="">请选择</option>,没加disabled selected,用户没动它,就一直卡在校验失败状态 - 移动端 WebView(比如旧版微信内置浏览器)直接忽略
required,连checkValidity()都返回true,必须额外降级检测
想让红边/星号/提示文字立刻可见,不能只靠 required
:invalid 伪类一加载就生效,导致页面刚打开所有必填框全变红。要让它“等用户动过再反馈”,得组合使用:
- 给
input加placeholder,然后用input:invalid:not(:placeholder-shown)控制样式,避免初始误标 - label 后加星号不能只靠 CSS:
label::after { content: " *"; color: #d32f2f; },还得同步写aria-required="true"保证读屏器可识别 - 如果需要失焦即提示(而非等提交),必须监听
blur,手动调input.reportValidity()—— 它会触发原生气泡,且返回布尔值供你判断 - 别在
input事件里反复调setCustomValidity(),容易让浏览器内部 validity 状态混乱;清空错误必须显式调input.setCustomValidity("")
自定义提示文案的唯一可靠路径
浏览器默认提示(如“请填写此字段”)无法通过 HTML 或 CSS 修改,title 属性在 Chrome 可临时覆盖,但 Firefox 不认、Safari 不稳定,不能当主力方案。
真正可控的方式只有 setCustomValidity(),但必须严格配对:
- 校验失败时:调
input.setCustomValidity("手机号不能为空") - 用户输入后:必须立刻调
input.setCustomValidity(""),否则哪怕填了内容,下次提交仍报上次的错 - 若用在
submit事件里,得先遍历所有字段统一清空,再逐个检查并设错,否则部分字段的旧错误状态会残留 - 一旦调过
setCustomValidity(),原生提示就永久被覆盖,想恢复?只能删掉这行代码,或者重置整个表单
最易被忽略的一点:当表单用 JS 提交(比如封装成 submitForm() 函数),required 完全不触发 —— 你得手动调 form.checkValidity() 或 form.reportValidity(),否则等于裸奔。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











