如何避免在 BEM 级联中重复父类名?

How to avoid repeating the parent classname in BEM cascade?

示例代码(我知道可以重写什么以避免级联,但我将其写为示例。这段代码不是真正的问题,我可以在另一个中解决方式,这只是插图):

.b-list {  
  //…

  &__item {
    //…
  }

  &__link {
    height: 4px;
    //…

    @at-root .b-list__item.-active & {
      height: 12px;       
    }     
  }
}

编译为:

.b-list__link {
  height: 4px;
}

.b-list__item.-active .b-list__link {
  height: 12px;
}

我想更改选择器@at-root .b-list__item.-active &
类似于 @at-root &__item.-active & {…}
避免重复父类名,但在 Sass:

时不起作用

此代码无效:

.b-list {  
  //…

  &__item {
    //…
  }

  &__link {
    height: 4px;
    //…

    @at-root &__item.-active & {
      height: 12px;       
    }     
  }
}

所以,有办法做我想做的事吗?

有一些方法可以在没有 @at-root 样式函数的情况下实现您正在寻找的代码。然而,由于这是最初的问题,下面应该可以解决问题。

您可以将 & 应用于变量,稍后通过嵌套将其作为 class 名称的一部分进行转义,如下所示:

.b-list {
    $rootParent: &;
    &__link {
        height: 4px;

        #{$rootParent}__item.-active & {
            height: 12px;
        }
    }
}

看起来很疯狂,但确实有效!

如果您想以更标准化的方式重新创建上述内容,我肯定会推荐以下内容:

.b-list {
    &__link {
        height: 4px;
    }

    &__item.-active &__link {
        height: 12px;
    }
}

通读 http://sass-guidelin.es/#selector-nesting 也很值得,特别是关于 BEM 命名的部分 & 当前选择器参考指出:

While it might be anecdotal, generating new selectors from the current selector reference (&) makes those selectors unsearchable in the codebase since they do not exist per se.

通常的做法是使用一个 "root" 变量并分配一个块的名称,但我发现它不是很优雅,所以构建了一个名为 superbem 的简单库。它是几个 Sass 混合宏,可帮助您以声明方式坚持使用 BEM 命名。您的示例如下所示:

@include block(b-list) {
    @include element(link) {
        height: 4px;
    }

    @include element(item) {
        &.-active {
            @include element(link) {
                height: 12px;
            }
        }
    }
}