必须在submit事件中调用event.preventdefault()后手动遍历所有required元素,检查value.trim()是否为空,并统一添加error类;提交成功后须清除所有error类,确保状态闭环。(149字符)

submit 事件中遍历 required 字段并加 error 类
表单提交失败时,必须主动让所有空的必填字段视觉可辨——仅靠 :invalid 伪类不够,因为部分浏览器在首次提交前不触发该状态。正确做法是在 submit 事件里调用 event.preventDefault(),然后手动检查每个 required 元素的值是否为空,并添加统一的 error 类。
常见错误是只弹 alert 或只改 style.border,导致样式散乱、无法复用、清空后残留红框。
- 用
form.querySelectorAll('input[required], select[required], textarea[required]')批量获取所有必填控件 - 对每个元素检查
!el.value.trim()(注意select要读el.value,textarea同样需trim()) - 统一用
el.classList.add('error'),而非el.style.borderColor = 'red'——前者可被 CSS 收口,后者易被后续 JS 覆盖 - 提交成功后,务必调用
form.classList.remove('error')并遍历清除各字段的error类,否则连续提交会累积高亮
CSS 中用 :invalid:user-invalid 精准控制红边框
纯 CSS 方案可行,但必须组合使用 :invalid 和 :user-invalid,否则会出现“页面一打开就全红”或“用户输错了还不红”的问题。:user-invalid 是关键:它只在用户与字段交互过(focus/blur、输入后删除等)且验证失败时才匹配,比 :invalid 更贴近真实操作流。
老浏览器不支持 :user-invalid?没关系,回退到 :invalid 不影响功能,只是初始状态更保守。
- 写法示例:
input:required:invalid:user-invalid, input:required:invalid:not(:placeholder-shown) -
:not(:placeholder-shown)排除 placeholder 还在显示的场景,避免误判为空 -
textarea和select不支持:placeholder-shown,需单独补充规则,例如:textarea:required:invalid:user-invalid - 边框生效三要素缺一不可:
border-width、border-style(如solid)、border-color;只写border-color: red是无效的
setCustomValidity() + reportValidity() 触发原生红框和气泡
如果后端返回了具体错误(比如 “邮箱已被注册”),就不能只靠 required 或正则 pattern,得用 JavaScript 注入业务级校验逻辑。核心是 setCustomValidity() 配合 reportValidity() —— 前者设状态,后者真正触发 UI 反馈(包括红边框和气泡提示)。
常见坑:只调 setCustomValidity('xxx') 却不调 reportValidity(),结果什么也不显示;或者在 submit 事件里 preventDefault() 后又指望原生气泡弹出来——这不可能,浏览器默认流程已被阻断。
-
inputElement.setCustomValidity('邮箱已被占用')设定错误信息 - 立刻跟一句
inputElement.reportValidity(),才能看到红框+气泡 - 清空错误必须传空字符串:
inputElement.setCustomValidity(''),否则下次校验仍会失败 - 不要在
input事件里调reportValidity(),它会频繁弹窗打断用户,体验极差;适合用在blur或提交前校验
border-collapse 影响表格内表单控件边框显示
如果表单控件嵌在 <table> 里(比如后台管理系统的编辑页),加了红色边框却看不见,八成是 <code>border-collapse: collapse 在作祟。这个属性会让相邻单元格边框合并,你的 input 边框可能被 td 的边框压住或裁掉。
别急着删 collapse,先确认是否真需要它——多数情况下,表单控件不需要和表格边框强耦合。
- 临时调试:给
input加outline: 2px solid #e53e3e,它不参与布局,也不受border-collapse影响,能快速验证是否是层叠问题 - 若必须保留
collapse,可在td上加padding并把input的border改为outline,避免视觉冲突 - 批量控制时,优先用 class(如
.has-error input)而不是直接操作style,方便后续维护和主题切换
classList.add 用了≠不会残留,reportValidity() 调了≠适合所有时机——关键在状态生命周期的闭环管理。前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











