正确命名是 carousel__indicator,它是轮播图容器的子元素而非独立组件;激活态用 carousel__indicator--active;容器 carousel__container 仅承载约束,轨道 carousel__track 负责位移;垂直轮播应另起块名 carousel-vertical 而非修饰符;指示器点击逻辑不应体现在类名中。
bem-block__element--modifier 还是 bem-block__element?轮播图容器包含的子功能单元才是指示器(dots)的属性,它并不构成独立组件,因此必须作为 carousel 的子元素存在,不能独立抽象为 dot 块。规范的命名应为 carousel__indicator —— 它表达的是容器的「指示器」,而非「一个指示器」。需要添加当前激活等状态时,应使用修饰符 carousel__indicator--active,不要写成 carousel__indicator-active(后一种写法违背 BEM 的双下划线规则)。
常见的错误包括:
• 命名为 dot 或 indicator 复用时作用域无法得到约束 ← 样式采用独立块名而失去上下文
• 把激活状态写为 carousel__indicator-active → 语义层级会被破坏,原因是开发者/BEM 解析器会把它当成另一个元素
移动端尤其需要注意:指示器通常要适配 touch,只有命名稳定,才能准确地将 touchstart 事件委托至 .carousel__indicator 上。
carousel__container 怎样划分 carousel__track 和容器(carousel__container)之间的职责?容器仅负责「承载与约束」,包括设置固定宽高、overflow: hidden以及定位上下文(例如 position: relative)。滑动逻辑不由它承担。
立即学习“前端免费学习笔记(深入)”;
实际执行位移的是内部轨道(carousel__track):它负责包裹全部 carousel__slide,由 slide 数 × 单张宽度得出整体宽度,再通过 transform: translateX() 或 scrollLeft 完成滚动。两者必须彻底分离,否则会造成 CSS 动画卡顿,并使 JS 偏移量计算出错。
实操建议:
• carousel__container 加 will-change: transform(仅当内部有频繁 transform 时)
• carousel__track 必须设 display: flex 或 white-space: nowrap 防止换行
• 不要在 carousel__container 上写 transform,那会干扰子元素的 transform 层级
carousel--vertical 此类修饰符?移动端很少单独采用垂直轮播,而且其交互逻辑(如 swipeY vs swipeX)、指示器布局(横向 dots 改为纵向 bars),乃至分页逻辑都完全不同。若强制用修饰符统一处理,不仅会让 CSS 膨胀,还会增加 JS 判断分支,使可维护性大幅下降。
更合适的处理方式是:
• 水平轮播继续使用 carousel 块名
• 垂直场景另建块名,例如 carousel-vertical(属于新块,并非修饰符)
• 可以共享基础工具类(例如 is-hidden、is-swiping),但结构样式不要共享
性能方面的影响:carousel--vertical 通常需要重新编写 carousel__indicator 中不只要调整 touch 事件坐标的计算方式,还涉及 transform 方向与 flex-direction;这些改动带来的测试成本和实际代码量,比另建轻量块高得多。
不要让 JS 行为出现在 BEM 命名中,其表达对象应当只是 UI 角色。反例包括 carousel__indicator--js-clickable 或 carousel__indicator--bound —— 这类名称会使后续维护者误以为“缺少这个类便无法点击”,但实际的点击逻辑应由 JS 统一绑定到 .carousel__indicator,然后通过 data-index 或 DOM 位置获取目标 slide。
规范做法如下:
• 指示器默认具备交互能力,名称应保持语义中立:carousel__indicator
• 当前激活状态使用 carousel__indicator--active(仅用于视觉反馈)
• loading 期间等情况下,某指示器若需暂时停用,则用 carousel__indicator--disabled,不要采用 JS 专用类名
真正需要在 JS 中监听的是相应处理;BEM 命名与此无关。常被忽视的背景是,移动端的 click 存在 300ms 延迟 touchend 并 preventDefault。这套逻辑不取决于 class 名称,因此不要让命名承担本应由 JS 明确表达的职责。