2

我有以下 mixin 可以轻松使用 BEM 语法和sass 3.3.2代码:

=b($name)
  .#{$name}
    @content

=e($name)
  &__#{$name}
    @content

=m($name)
  &--#{$name}
    @content

+b(menu)
  +e(item)
    color: grey
  +e(item)
    +m(alert)
      color: red

这给了我想要的结果:

.menu__item {color: grey;}
.menu__item--alert {color: red;}

所以这对元素级修饰符非常有效,但是当我想要块级修饰符时,问题就开始了:

+b(menu)
  +m(theme-1)
    +e(item)
      color: blue

css输出:

.menu--theme-1__item {color: blue;}

当我真正想要的是:

.menu--theme-1 .menu__item {color: blue;}

所以我需要一种方法来检查元素的上下文是什么,当上下文是块时没有问题,但当是修饰符时语法失败。我尝试在 e mixin 中将父选择器作为字符串,所以当父选择器e没有b语法--时,反之,当父选择器m--语法时,我可以决定两个上下文使用什么语法。我没有找到将父选择器作为字符串的方法,我认为这是不可能的,有没有办法让它工作?

更新 我发现一个不是很简单的解决方案可以正常工作,它在元素混合中使用上下文参数:

=e($name, $context:null)
  @if $context
    &
      +b($context)
        &__#{$name}
          @content
  @else
    &__#{$name}
      @content

现在我可以按如下方式调用mixin:

+b(menu)
  +m(theme-1)
    +e(item, nav)
      color: blue

得到:

.menu--theme-1 .menu__item {color: blue;} 
4

1 回答 1

0

回答一个 2 岁的问题 - 远射:) 但希望也能帮助其他人。

因此,一种更强大的方法是改进您的 Element mixin 以检查父选择器是否具有修饰符。

所以你需要2个功能:

  • 检查选择器是否包含修饰符
  • 一个从该选择器中获取块名称

@function _bem-selector-has-modifier($selector) {
  $selector: _bem-selector-to-string($selector);

  @if str-index($selector, $bem-modifier-separator) or str-index($selector, ':') {
    @return true;
  } @else {
    @return false;
  }
}


@function _bem-get-block-name($selector) {
  $selector: _bem-selector-to-string($selector);
  $modifier-separator: '--';

  $modifier-start: str-index($selector, $modifier-separator) - 1;

  @return str-slice($selector, 0, $modifier-start);
}

然后你只需要在你的元素混合中应用检查

$bem-element-separator: '__';

@mixin element($element) {
  $selector: &;

  @if _bem-selector-has-modifier($selector) {
    $block: _bem-get-block-name($selector);

    @at-root {
      #{$selector} {
        .#{$block + '__' + $element} {
          @content;
        }
      }
    }
  } @else {
    @at-root {
      #{$selector +'__' + $element} {
        @content;
      }
    }
  }
}

element('item')所以在 a 内部调用modifier('with-modifier')应该在你编译的 CSS 中呈现一个.block--with-modifier .block__item选择器,你不必手动传递上下文。

贴出的代码是SCSS,但思路应该和SASS一样。

于 2016-06-30T11:44:58.977 回答