Uni-app中BEM规范需严格绑定文件名:组件UserCard.vue对应block为user-card,页面ProfilePage.vue对应profile-page;禁止跨文件复用block、平台后缀修饰符及SCSS多层嵌套,第三方组件须用BEM wrapper封装。

Uni-app 项目里直接套用 Web 端的 BEM 规范会踩坑——不是类名写错,而是块名语义模糊、跨端样式隔离失效、SCSS 嵌套越界,最终导致 H5 正常、小程序错位、App 字体缩放异常。
uni-app 中 block 名必须绑定组件文件名
在 UserCard.vue 里写 .user-card 是合法 block;但若在 pages/user/ListPage.vue 里也用 .user-card,就等于把两个不同生命周期、不同数据流的上下文混在同一命名空间下。Uni-app 的页面和组件是强隔离单元,BEM 的 block 必须与文件粒度对齐。
- ✅ 正确:组件
UserCard.vue→ block 名为user-card;页面ProfilePage.vue→ block 名为profile-page - ❌ 错误:所有用户相关 UI 都用
user作 block,如user__avatar,它无法区分是卡片头像还是弹窗头像 - ⚠️ 注意:
pages/下的页面级 block 不建议复用组件 block,哪怕结构相似——因为页面有路由守卫、onLoad 生命周期等独有逻辑,样式域必须物理隔离
element 命名禁止带平台后缀或断点暗示
写 user-card__avatar--h5 或 user-card__avatar@sm 是典型反模式。Uni-app 的多端适配靠条件编译(#ifdef MP-WEIXIN)和 rpx 单位驱动,不是靠类名承载平台逻辑。修饰符只表达状态,不表达环境。
- ✅ 正确:
user-card__avatar--loading(加载态)、user-card__avatar--error(加载失败),JS 控制增删 - ❌ 错误:
user-card__avatar--mp、user-card__avatar--large-screen,这类类名会让 PostCSS 校验器报错,且无法被 UnoCSS 的 BEM 模式识别 - ? 实操:需要平台差异样式时,统一用
user-card__avatar作为锚点,在 SCSS 中用条件编译包裹媒体查询或平台特有声明
SCSS 中嵌套必须严格单层,且禁用空格后代选择器
Uni-app 默认启用 Vue SFC 的 scoped 样式,但 BEM 的价值不在作用域隔离,而在语义可追溯。如果在 user-card.scss 里写 .user-card { &__header { &__title { color: red; } } },生成的 .user-card__header__title 违反 BEM 元素不可嵌套原则,且小程序端可能因样式提升(style lifting)行为导致类名丢失。
立即学习“前端免费学习笔记(深入)”;
- ✅ 正确:SCSS 中只用
&__element和&--modifier,绝不出现&__element &__icon(含空格) - ❌ 错误:
.user-card__header { .user-card__title { ... } }或&__header { &__title { ... } } - ? 工具建议:在
vue.config.js中接入postcss-bem-linter,配置allowedPatterns为/^([a-z][a-z0-9-]*)(__[a-z][a-z0-9-]*)?(--[a-z][a-z0-9-]*)?$/,自动拦截非法命名
第三方组件必须 wrapper 封装,不能直接覆盖类名
Element Plus、uView、uni-ui 的内部类名(如 .uni-btn、.u-button)不符合 BEM,强行加 !important 覆盖或用深度选择器(:deep(.uni-btn))会破坏 scoped 隔离,且 H5 和小程序编译结果不一致。
- ✅ 正确:用 wrapper 容器绑定 block,例如
<div class="user-card__action-bar"><u-button></u-button></div>,再通过.user-card__action-bar .u-button局部重置 - ❌ 错误:在
user-card.scss中直接写.u-button { background: var(--primary); },该规则会泄漏到其他页面 - ? 关键点:wrapper 的 class 必须是完整 BEM 形式(如
user-card__action-bar),不能是action-bar这类孤立名,否则失去上下文归属
BEM 在 uni-app 里最易被忽略的,是 block 名与文件路径的耦合强度——它不是命名习惯,而是编译期依赖。一旦 components/common/UserCard.vue 被挪到 components/mp/UserCard.vue,block 名就得同步改为 mp-user-card,否则 H5 端的样式会意外作用于小程序组件实例。


















