鲁迅说过:只有阅读过优秀库源码的人,才能配的上是真正的勇士。
BEM
BEM是一种前端命名方法论,主要是针对CSS,意思是块(Block)、元素(Element)、修饰符(Modifier)的简写。这种命名方法让CSS便于统一团队开发规范和方便维护。
BEM规定是块和元素之间用__连接,元素和修饰符之间用–连接
在SassMagic中mixins下有个_BEM.scss文件,它把BEM拆分成为b,e,m这三个mixins。我们来看下它们是如何进行工作的。
@mixins b($block){
.#{$block}{
@content;
}
}
以上的代码知识点分为2个,
1. 通过 #{} 插值语句可以在选择器或属性名中使用变量,
2. @content,向混合样式中导入内容 ,换句话来说可以通过@content向mixins注入你想要的样式,并且和合并原有的样式,合并的原则会和CSS中合并规则一样。
demo
@mixin b($block){
.#{$block}{
background-color: blue;
@content;
}
}
@include b(test){
color: red;
}
结果
.test {
background-color: blue;
color: red;
}
E
在BEM中,E主要是用来连接块与块的功能,一般情况下会使用"__"两个下划线来表示。所以,我们则定义一个变量。
$elementSeparator: '__';
@mixin e($element) {
$selector: &;
@if containsModifier($selector) {
$block: getBlock($selector);
@at-root {
#{$selector} {
#{$block+$elementSeparator+$element} {
@content;
}
}
}
} @else {
@at-root {
#{$selector+$elementSeparator+$element} {
@content;
}
}
}
}
相对来说这个Emixins,就比较复杂,我总结以下知识点:
- $selector: &;代表的是当前块元素。
- containsModifier,判断
$selector
中是否包含BEM中Modify - getBlock,将
$selector
转换成String - @at-root,是Sass3.3.0中新增的功能,用来跳出选择器嵌套的,默认所有的嵌套,继承所有上级选择器,但有了这个就可以跳出所有上级选择器。
在SCSS中我们可以定义function来对样式来进行操作,而上面的containsModifier,getBlock都是函数,定义函数则需要通过@function这个关键字进行声明。
containsModifier
/// 判断`$selector`中是否包含BEM中Modify
/// @access private
/// @param {String} $selector
/// @return {Boolean} `true` or `false`
@function containsModifier($selector) {
$selector: selectorToString($selector);
@if str-index($selector, $modifierSeparator) {
@return true;
} @else {
@return false;
}
}
selectorToString
/// 将`$selector`转换成String
/// @access private
/// @param {String} $selector
/// @return {String} $selector
@function selectorToString($selector) {
$selector: inspect($selector); //cast to string
$selector: str-slice($selector, 2, -2); //remove brackets
@return $selector;
}
以上代码涉及了一下知识点。
- inspect内置函数。
- str-index 内置函数,返回 substring 子字符串第一次在 string 中出现的位置。
E
@mixin e($element) {
$selector: &;
@if containsModifier($selector) {
$block: getBlock($selector);
@at-root {
#{$selector} {
#{$block+$elementSeparator+$element} {
@content;
}
}
}
} @else {
@at-root {
#{$selector+$elementSeparator+$element} {
@content;
}
}
}
}
m
@mixin m($modifier) {
@at-root {
#{&}#{$modifierSeparator+$modifier} {
@content;
}
}
}
demo
/// @include b(block) {
/// background: red;
/// @include e(header){
/// font-size: 14px;
///
/// @include m(css) {
/// font-size: 18px;
/// }
/// };
/// }
/// //CSS
/// .block {
/// background: red;
/// }
/// .block__header {
/// font-size: 14px;
/// }
/// .block__header--css {
/// font-size: 18px;
/// }