独立组件(block)和子元素(element)的区分标准是能否脱离父容器独立存在:能单独复用、有独立样式/行为/测试、出现在多个上下文中的即为block,如avatar;否则为element,如card__title,且必须是block的直接子节点。

独立组件(Block)和子元素(Element)的区分,不看大小、不看嵌套深浅,只看它能不能“自己活”。能脱离父容器单独用、有自己样式逻辑、跨上下文复用的,就是 Block;否则就是 Element。
判断标准:删掉父级后,它还能不能跑起来
这是最硬的检验方式。不是“视觉上像不像独立模块”,而是实际工程中它是否具备独立存在能力:
- 有自己完整的 CSS 文件(比如
avatar.css),不依赖user-card.css才能渲染 - 有配套 JS 行为(如点击放大、加载头像状态),且逻辑不耦合于父组件生命周期
- 在测试用例里能被单独 mount 和断言(例如
render(<avatar></avatar>)) - 出现在至少两个无关上下文中(如用户卡片、评论区、个人设置页)
满足以上任意一条,它就该是 Block,命名用 avatar、tag、chip;全都不满足,才考虑写成 user-card__avatar。
DOM 结构验证:Element 必须是 Block 的直接子节点
BEM 对 HTML 层级有硬性约束:card__title 对应的标签必须紧贴 card 标签下一级,中间不能插层。常见翻车点:
- 误写:
<div class="card"><div class="card__inner"><h2 class="card__title">...</h2></div></div>→card__title实际嵌套在card__inner下,违反规则 - 正确写法:
<div class="card"><h2 class="card__title">...</h2></div>,或把card__inner升级为新 Block(如card-body),再让card-body__title归属它 - SCSS 中用
&__content { &__title {} }会生成card__content__title—— 语法合法,语义非法,BEM 不允许双下划线嵌套
命名陷阱:别被“小”和“在内部”带偏节奏
很多团队一看到“按钮里的图标”,就本能写 button__icon,但真正该问的是:“这个图标有没有自己的变体?比如不同颜色、尺寸、加载态?会不会用在输入框、卡片、导航栏里?”
- 如果只是按钮里一个固定尺寸的 SVG,没样式变化、没复用场景,它甚至不该有类名——用
button svg或继承处理更轻量 - 如果它是可配置的通用图标组件(支持
icon--size-m、icon--color-primary),那它就是 Block,叫icon,而不是任何__icon - 把
section-2、block-wrapper这类纯视觉分组当 Block,本质是用 BEM 给无语义结构贴金,反而增加维护负担
修饰符锚定位置暴露归属关系
button--disabled 合法,card__title--large 也合法,但 --disabled 单独出现就失效——BEM 要求 Modifier 必须挂靠在明确的 Block 或 Element 上,靠命名自带作用域。
- 写
card--featured没问题,但不能因为 card 里有个标题,就给它加card__title--featured—— “特色”是整张 card 的状态,不是标题的状态 - 同理,
nav__item--active合理,因为激活态属于 nav item 本身;但header__nav__item--active是错的,header__nav本身就违反 BEM,nav应是独立 Block - 一旦发现某个 Modifier 需要同时作用于多个层级(比如既要改 card 样式又要改 card__title 字体),说明语义划分可能错了,该拆 Block 而不是硬塞修饰符
真正难的不是记住 __ 和 -- 怎么写,而是在加每一个新类名前,停半秒问:“它有没有资格独立存在?” 答错一次,后面就得花十倍力气重构。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











