只能用 form-field--invalid 一个修饰符,因其语义唯一、避免误判与视觉错乱;必须挂载在字段容器上,确保样式可统一控制 label、input、error 等关联元素;禁止多修饰符堆砌,错误类型由 error 文本内容表达。

表单验证的错误状态类名必须只用 form-field--invalid,挂载在字段容器上,其他所有变体(如 form-field--valid、form__input--error、form--invalid)都属于误用,会破坏状态语义、干扰无障碍、增加维护成本。
为什么只能用 form-field--invalid 一个修饰符
验证状态天然互斥:一个字段同一时刻只能是“未校验”“有效”“无效”之一。但 form-field--valid 极易触发语义误判——用户刚输完邮箱,JS 立刻加这个类,可此时表单根本没提交,后端还没校验,业务逻辑上它并不“有效”。更现实的问题是视觉错乱:空字段初始就被 :valid 触发绿色边框;或输入后立刻变绿,提交失败又跳红,用户信任直接崩塌。
只保留 form-field--invalid 作为唯一 JS 主动控制的类,意味着:
- JS 校验返回
false时添加,返回true或undefined时移除 - 初始态不依赖任何修饰符,靠
.form-field__input:not(:placeholder-shown)或form-field--touched区分是否已输入 - 如需密码强度等实时确认,可用
form-field--touched form-field--valid组合,但form-field--valid绝不能单独出现
form-field--invalid 必须挂在字段容器上,不能挂 input 或 form
常见错误是把类加在 input 上,比如 form__input--error。这违反 BEM 原则:Element(__input)不能带 Modifier(--error),且样式只能作用于 input 自身,无法同步控制 label 颜色、错误文案显隐、icon 状态等关联行为。
正确结构是让修饰符落在字段级 Block 容器上:
<div class="form-field form-field--invalid"> <label class="form-field__label">邮箱</label> <input class="form-field__input"><div class="form-field__error">请输入正确的邮箱地址</div> </div>
CSS 通过后代选择器统一驱动:
-
.form-field--invalid .form-field__input控制边框 -
.form-field--invalid .form-field__label控制颜色 -
.form-field--invalid .form-field__error控制显隐
禁止挂在 form 元素上——否则一个字段错,整表单变红,用户无法定位问题,语义彻底错乱。
多个规则共存时,别堆砌修饰符
不要写 form-field--required --email --max-len 这类多修饰符组合。CSS 权重会失控,改一个可能意外影响另一个;更重要的是,它把校验逻辑泄漏到类名里,JS 得反复拼字符串,维护成本指数上升。
BEM 修饰符不是日志,而是契约:一个字段在同一时刻只有一个对外暴露的状态信号。
- 统一用
form-field--invalid表达“校验失败” - 具体错误类型(空、格式错、域名白名单不通过)由
form-field__error的文本内容决定 - 如需区分错误来源(前端格式错 vs 后端冲突),可用
form-field--invalid-server这类语义化变体,但必须提前约定、全局收敛,不能随 JS 判断临时生成
最常被忽略的点是:修饰符命名一旦定下,就和 JS 校验逻辑强绑定;而真实项目中,后端返回的错误码、文案格式、甚至字段粒度都可能频繁变动。所以 form-field--invalid 是底线,不是起点——它背后需要一套稳定的校验结果归一化层,把各种原始错误映射到有限、可枚举的状态信号上,否则类名很快就会变成没人敢动的遗留代码。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











