商品卡片必须作为独立 block(product-card),而非 product-list__card,因其需脱离列表上下文在邮件、弹窗等场景单独复用;嵌套命名会导致样式绑定、ci报错、purgecss误删及工具链失效。

电商商品卡片必须拆成独立 product-card Block,不能套用 product-list__card 这类嵌套前缀——否则无法在邮件模板、弹窗或推荐位中单独复用,CI 构建时 stylelint-selector-bem-pattern 会直接报错。
为什么 product-card 必须是 Block,而不是 product-list__card
Block 的核心判据是「能否脱离上下文独立存在」。商品卡片在搜索页、购物车侧边栏、邮件营销模板里都需原样渲染,它自带完整交互逻辑(加购、收藏、悬停展开)、主题变量和响应式断点。一旦写成 product-list__card,就等于把它的样式和生命周期绑定到列表容器上:
- 邮件模板中引入卡片时,得连带加载整个
product-listCSS,体积暴增 -
product-list__card在 VS Code 中无法被 PostCSS 插件识别为合法 BEM 元素,补全失效 - 构建时 PurgeCSS 会误判
product-list__card为非关键类而删除,导致线上漏样式
product-card__image 和 product-card__price 这些元素名怎么定才不越界
Element 名必须表达「它是什么」,而非「它用什么标签实现」或「它长什么样」。常见错误是照搬 DOM 结构写成 product-card__img 或 product-card__div-price,这会让语义断裂、工具链拒绝识别:
-
product-card__image✅ —— 表达“主视觉区域”,可渲染<img>、<video></video>或占位 SVG -
product-card__price✅ —— 表达“价格信息区”,内部可含<span class="price-tag"></span>独立 Block -
product-card__badge❌ → 应拆为独立badgeBlock,再通过product-card__badge-wrapper容器组合 -
product-card__title不可缩写为product-card__head—— “head”语义模糊,易与product-card__header-icon混淆
修饰符该挂 product-card--on-sale 还是 product-card__price--discounted
Modifier 必须依附于明确的宿主,且只表达意图,不暴露实现细节。状态类(如 loading / disabled)应统一用 is- 前缀,避免和 BEM 主结构耦合:
-
product-card--on-sale✅ —— 「促销中」是卡片整体业务状态,影响 image、price、badge 多个元素 -
product-card__price--discounted❌ —— 折扣逻辑本应由price-tagBlock 自身管理,强行挂载到卡片元素上破坏职责分离 -
is-loading✅ —— JS 控制时只需增删该类,不侵入 BEM 结构;CSS 中写.product-card.is-loading .product-card__image是允许的例外 -
product-card--horizontal✅ —— 影响多子元素布局逻辑的跨页面变体,不是临时样式开关
SCSS 嵌套时怎么避免编译出后代选择器破坏封装
所有 SCSS 嵌套必须只用 &__ 和 &--,空格会生成后代选择器,直接泄漏 DOM 层级依赖:
- 错误:
.product-card { &__content { .icon { ... } } }→ 编译出.product-card__content .icon,一旦图标移入__footer就失效 - 正确:
.product-card { &__content { ... } &__icon { ... } &--on-sale { ... } }→ 输出全是扁平类名 - 真需控制子元素样式(比如 icon 颜色随卡片主题变),优先用属性选择器:
[data-role="icon"],而非靠类名猜结构
最常被忽略的是:BEM 不是给 class 加前缀,而是用命名提前钉死组件的复用边界。一旦允许 icon--sm 这种脱离块名的全局类,或者靠 [class*="--"] 模糊匹配提取修饰符,整个约束体系就塌了。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











