必须将分类页拆分为独立block:category-filter、category-item、category-dropdown、category-ad-banner、pagination等,因bem禁止element嵌套element,且各模块数据源、交互逻辑、复用场景不同。

电商分类页的列表结构看似只是
- 嵌套,但实际常混杂筛选项、广告位、分页、加载态、多级子类等。直接用
.category-list__item一路往下套,很快会遇到命名冲突、状态难控、复用困难的问题——根本原因不是写法错,而是没按交互和语义边界切分 Block。为什么不能把整个分类树塞进一个
category-treeBlock常见错误是定义一个顶层
.category-tree,然后所有节点都用.category-tree__node、.category-tree__node__child这类写法。这违反 BEM 核心原则:Element 不得嵌套 Element,且 Block 必须具备独立功能与复用价值。-
.category-tree__node__child是非法命名,BEM 禁止三层结构;真实业务中“子类展开面板”需要独立控制动画、z-index、键盘导航逻辑,它不是一个视觉子元素,而是一个可触发、可挂载、可单独测试的交互单元 - 广告位(如“品牌专区”)和普通分类项渲染逻辑不同、数据源不同、埋点不同,硬塞进同一 Block 会导致 JS 状态管理耦合、CSS 权重失控
- 移动端折叠/展开行为通常只作用于某一层,若全靠
.category-tree--expanded控制,就无法实现“一级展开、二级收起”的混合状态
哪些部分必须拆成独立 Block
分类页中真正该作为顶层 Block 存在的,不是“树”,而是有明确职责边界的可复用单元:
-
category-filter:负责筛选条件(价格区间、属性多选、排序),内部用category-filter__control、category-filter__option,不和分类列表共享任何类名前缀 -
category-item:每个可点击的分类项(含图标、文字、角标),支持category-item--has-children、category-item--active等修饰符,它不关心自己是否在树里,只管自身状态 -
category-dropdown:子类展开面板,和导航菜单中的dropdown是同一套组件,复用dropdown__toggle、dropdown__menu,仅通过 modifier 如dropdown--in-category微调定位 -
category-ad-banner:广告位,完全独立,内部结构自包含,不依赖父级上下文
HTML 中它们的关系是平级并列:
<div class="category-filter"></div> <div class="category-list"></div>,而不是嵌套。category-list这个 Block 到底该管什么category-list只承担两件事:布局占位 + 语义容器。它不定义任何子项样式,也不处理展开逻辑,只声明“这里是一组分类项的集合”。- 它的子元素只能是
category-list__item,且每个category-list__item必须是一个完整的category-item实例,即:<li class="category-list__item"><div class="category-item">...</div></li> - 禁止写
.category-list__item .category-item这类后代选择器——这等于把两个 Block 的样式逻辑耦合在一起,违背 BEM “样式只属于一个 Block” 原则 - 分页、加载更多按钮不属于
category-list的 Element,应是独立 Block:pagination或load-more-button,放在category-list外部或底部即可
多级子类展开时,
category-item和category-dropdown怎么配合关键在 DOM 结构对齐:子类面板必须是触发项的相邻兄弟节点,或严格包裹关系,否则
:hover、:focus-within、:has()都会失效。- 正确结构:
<div class="category-item"> <button class="category-item__trigger">手机</button><div class="category-dropdown"><div class="category-dropdown__menu">...</div></div> </div> - 错误结构:中间插入
<span></span>、<transition></transition>或 Fragment 导致.category-item__trigger和.category-dropdown不再是直接父子或相邻兄弟 - 二级子类不是
category-item__submenu,而是另一个category-dropdown实例,里面的内容是category-item列表 —— 复用而非复制
真正容易被忽略的是:Block 边界不是由视觉层级决定的,而是由数据来源、交互职责、复用场景共同定义的。写错一次命名,后期加个“仅在首页展示”逻辑,就得改三处 CSS、两处 JS、一堆测试用例。
-
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











