我有以下mixins,可以轻松使用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
parent为b
时,它将不具有--
语法,而在其他父级为{{1}时它将具有m
语法,我可以决定两种语境使用什么语法。
我没有找到一种方法将父选择器作为一个字符串,我认为是不可能的,有没有办法使这个工作?
更新 我找到了一个不太直接的解决方案,它运行正常,它在元素mixin中使用了一个context参数:
--
现在我可以按如下方式调用mixin:
=e($name, $context:null)
@if $context
&
+b($context)
&__#{$name}
@content
@else
&__#{$name}
@content
得到:
+b(menu)
+m(theme-1)
+e(item, nav)
color: blue
答案 0 :(得分: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);
}
然后你只需要在元素mixin中应用检查
$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')
内调用modifier('with-modifier')
应该在已编译的CSS中呈现.block--with-modifier .block__item
选择器,您不必手动传递上下文。
发布的代码是SCSS,但这个想法应与SASS相同。