Dropdown 的 BEM 块名应为 dropdown;元素名需明确归属,如 dropdown__trigger、dropdown__menu、dropdown__option;修饰符应描述预设变体(如 dropdown--up),而非运行时状态。

Dropdown 的 BEM 块名该叫 dropdown 还是 select?
直接叫 dropdown。BEM 要求块名反映组件意图,不是 HTML 标签名——<select> 是原生控件,而业务中常见的下拉菜单多为自定义弹层(含搜索、分组、复选等),语义上属于“可展开的交互容器”,dropdown 更准确。用 select 容易和原生 <select> 混淆,后续维护时连 CSS 作用域都难区分。
常见错误:团队里有人写 ui-dropdown 或 myappDropdown——BEM 不需要前缀,块名本身应具备业务上下文辨识度;若项目内有多个下拉变体(如表单下拉 vs 导航下拉),可用 form-dropdown 或 nav-dropdown,但不要加技术前缀。
元素名怎么定:避免 dropdown__item 这种模糊命名
dropdown__item 看似合理,但实际会引发歧义:它指下拉列表里的选项?还是下拉触发区里的文字?还是整个下拉容器里的任意子节点?BEM 元素必须明确归属且不可复用。
推荐按真实 DOM 结构分层命名:
立即学习“前端免费学习笔记(深入)”;
-
dropdown__trigger:触发区域(按钮或输入框) -
dropdown__menu:浮层容器(<div class="dropdown__menu">) -
dropdown__list:菜单内的滚动内容区(常为<ul>) -
dropdown__option:单个可选条目(不用item,因option明确表达“可选语义”) -
dropdown__divider:分隔线(不叫separator,因 BEM 偏好名词化、短小、一致)
注意:dropdown__option 下如果还有图标或复选框,就继续用元素嵌套:dropdown__option-icon、dropdown__option-checkbox,而不是新建块。
修饰符怎么用:状态类别名别硬套 is-open
BEM 修饰符用于表示块或元素的**外观或行为变体**,不是通用状态钩子。把 is-open 当万能开关加在 dropdown 上,会导致样式耦合严重——比如 dropdown is-open 同时控制 trigger 旋转 + menu 显示 + 动画延迟,违反单一职责。
更合理的做法是:
- 用
dropdown--up表示弹层向上展开(影响dropdown__menu的top/bottom) - 用
dropdown--searchable表示带搜索框(此时会渲染dropdown__search元素) - 用
dropdown__option--disabled控制单个选项禁用态(不写dropdown__option is-disabled,修饰符必须绑定到目标元素)
关键区别:-- 修饰符描述的是**设计系统中预设的、可文档化的变体**,不是运行时临时状态。JS 控制显隐应该操作 dropdown__menu 的 display 或 visibility,而非靠 is-open 类切换整块逻辑。
为什么不能在 dropdown__menu 里再起一个 menu 块?
可以,但没必要,而且大概率是错的。BEM 中“块”代表独立、可复用的 UI 单元;dropdown__menu 是 dropdown 的一部分,不具备跨上下文复用价值——你不会在非下拉场景里单独用这个菜单容器。强行拆成独立块 menu,反而导致:
- 样式隔离失效(
menu的宽度/阴影需依赖dropdown上下文) - JS 事件委托断裂(原绑定在
dropdown上的click处理器无法自然捕获menu内部事件) - DOM 层级冗余(
<div class="dropdown"><div class="dropdown__menu"><div class="menu">...)
只有当某个子结构确实被多个不同父块复用(例如:所有弹层共用一套 popover 浮层逻辑),才考虑抽成独立块。否则,老老实实用 __ 表达从属关系,语义清晰,维护成本最低。
最易被忽略的一点:BEM 不是命名游戏,而是约束组件边界。类名一旦定下,就锁定了 DOM 结构预期——改一个 __ 名,往往意味着要同步改 JS 查询、测试断言、甚至设计标注。所以定名时多花两分钟想清楚“它到底是不是独立单元”,比后期重构省十倍力气。


















