element scss mixin BEM 实现

element scss mixins 学习

element scss 文件源码目录 element/tree/dev/packages/theme-chalk

theme-chalk/src/mixins/config.scss中,有对 element-ui的基础命名

$namespace: 'el';   //前缀名
$element-separator: '__';  //子元素连接符
$modifier-separator: '--'; //块样式状态连接符
$state-prefix: 'is-';   //状态前缀

theme-chalk/src/mixins/mixins.scss中,则定义了BEM的混合方法

/* BEM
 -------------------------- */
@mixin b($block) {
   // $block 即为传递进来的元素 比如 button 拼接之后 ==>  el-button
  //变量拼接形成对应格式的class;再使用!global将其提升为全局变量
  $B: $namespace+'-'+$block !global; 
    // 使用插值语法将$B这个选择器作为选择器使用 #{}
  .#{$B} {
    @content; //使用混合;大括号后定义的样式都会解析到这里
  }
}


@mixin e($element) {
  $E: $element !global;
  $selector: &;
  $currentSelector: "";
//@each内 其实就是变量拼接,通过__符连接父级选择器和传入的子元素,而传入的值可以单个,也可以是数组;
  @each $unit in $element {
    $currentSelector: #{$currentSelector + "." + $B + $element-separator + $unit + ","};
  }
// hitAllSpecialNestRule 为自己自定义函数
  @if hitAllSpecialNestRule($selector) {
    @at-root {
      #{$selector} {
        #{$currentSelector} {
          @content;
        }
      }
    }
  } @else {
    @at-root {
      #{$currentSelector} {
        @content;
      }
    }
  }
}

@mixin m($modifier) {
  $selector: &;
  $currentSelector: "";
  @each $unit in $modifier {
    $currentSelector: #{$currentSelector + & + $modifier-separator + $unit + ","};
  }

  @at-root {
    #{$currentSelector} {
      @content;
    }
  }
}


  • !global

变量支持块级作用域,嵌套规则内定义的变量只能在嵌套规则内使用(局部变量),不在嵌套规则内定义的变量则可在任何地方使用(全局变量)。将局部变量转换为全局变量可以添加 !global 声明:

  • @content
$color: white;
@mixin colors($color: blue) {
  background-color: $color;
  @content;
  border-color: $color;
}
.colors {
  @include colors { color: $color; }
}
/**
 *	编译后
*/
.colors {
  background-color: blue;
  color: white;
  border-color: blue;
}

BEM ==> B

$namespace:'dl';
@mixin b($block) {
  $B: $namespace+'-'+$block !global;
  //使用插值语法将$B这个选择器作为选择器使用
  .#{$B} {
    @content;
  }
}
@include b(button){
  border-radius: 4px;
  border: 1px solid #ebeef5;
  background-color: #fff;
  color: #303133;
  transition: 0.3s;
}
/**
 *	编译后
*/
.dl-button {
  border-radius: 4px;
  border: 1px solid #ebeef5;
  background-color: #fff;
  color: #303133;
  transition: 0.3s;
}
  • @at-root指令可以使一个或多个规则被限定输出在文档的根层级上,而不是被嵌套在其父选择器下。
.parent{
  color:red;
  @at-root .child {
    width:200px;
    height:50px;
  }
}
/**
 *	编译后
*/
.parent {
  color: red;
}
.child {
  width: 200px;
  height: 50px; 
}
  • hitAllSpecialNestRule ==> theme-chalk/src/mixins/function.scss
// @import "config";
$namespace: 'el';
$element-separator: '__';
$modifier-separator: '--';
$state-prefix: 'is-';


/* BEM support Func
 -------------------------- */
@function selectorToString($selector) {
  $selector: inspect($selector);
  $selector: str-slice($selector, 2, -2);
  @return $selector;
}
//inspect(value) 使用inspect(value)使用inspect( value)函数来生成一个对调试Map有用的输出字符串,因为Map无法转换为纯CSS。使用一个作为CSS函数的变量或参数的值将导致错误。

//判断父级选择器是否包含'--'
//看看当前选择器是否存在$modifier-separator这个变量也就是"--";
@function containsModifier($selector) {
  $selector: selectorToString($selector);
//str-slice(string,string, string,start-at, end−at:−1)从end-at:-1) 从 end−at:−1)从string 中截取子字符串,通过 start−at和start-at 和 start−at和end-at 设置始末位置,未指定结束索引值则默认截取到字符串末尾。
  @if str-index($selector, $modifier-separator) {
    @return true;
  } @else {
    @return false;
  }
}
//判断 父级选择器是否包含'.is-'
//看看当前选择器是否存在$state-prefix这个变量也就是"is-";
@function containWhenFlag($selector) {
  $selector: selectorToString($selector);
//str-index(string,string, string,substring) 返回一个下标,标示 substring在substring 在 substring在string 中的起始位置。没有找到的话,则返回 null 值。这里$string必须为字符串
  @if str-index($selector, '.' + $state-prefix) {
    @return true
  } @else {
    @return false
  }
}
//判断 父级是否包含 ':'
//看看当前选择器是否存在":";用于判断伪类和伪元素
@function containPseudoClass($selector) {
  $selector: selectorToString($selector);

  @if str-index($selector, ':') {
    @return true
  } @else {
    @return false
  }
}

@function hitAllSpecialNestRule($selector) {

  @return containsModifier($selector) or containWhenFlag($selector) or containPseudoClass($selector);
}

https://juejin.cn/post/6894265906596642829
  • selectorToString 方法得执行
//这里有人可能觉得这里是多此一举,但其实这里是通过inspect和str-slice把传入的选择器变量转换为字符串;因为在str-index 函数中传入的str-index($string, $substring)中,$string 必须要是一个字符串

@function selectorToString($selector) {
  @debug "初始化的选择器: #{$selector}";   //打印结果为.mk-card
  $selector: inspect($selector);
  @debug "inspect格式化后的选择器: #{$selector}";  //打印结果为 (.mk-card)
  $selector: str-slice($selector, 2, -2);
  @debug "str-slice格式化后的选择器: #{$selector}";  //打印结果为.mk-card;所以我觉得这里不是多余的么
  $selector: inspect($selector);
  @return $selector;
}

来源 ===》 https://juejin.cn/post/6894265906596642829

我们可以看看含有这几个元素与不含这些元素的编译区别

//****************不含"--"、"is-"、 ":"
//编译前  不包含,则通过@at-root跳出选择器嵌套
.mk-card{
  $selector: &;
  @include e(footer) {
    //传入单个
    padding: 20px;
  }
}

//编译后
.mk-card__footer {
  padding: 20px;
}

//****************含"--"、"is-"、 ":"
//编译前 ;包含则嵌套于父级选择器下
.mk-card:hover {
  $selector: &;
  @include e(footer) {
    //传入单个
    padding: 20px;
  }
}
//编译后
.mk-card:hover .mk-card__footer {
  padding: 20px;
}
  • @mixin configurable-m(modifier,*m**o**d**i**f**i**e**r*,E-flag: false)
@mixin configurable-m($modifier, $E-flag: false) {
  $selector: &;
  $interpolation: "";

  @if $E-flag {
    $interpolation: $element-separator + $E-flag;
  }

  @at-root {
    #{$selector} {
      .#{$B + $interpolation + $modifier-separator + $modifier} {
        @content;
      }
    }
  }
}

@include b(card) {
  border-radius: 4px;
  border: 1px solid #ebeef5;
  background-color: #fff;
  overflow: hidden;
  color: #303133;
  transition: 0.3s;
  
  @include configurable-m(primary, task) {
    display: flex;
  }
  @include configurable-m(primary, false) {
    display: flex;
  }

}

//编译后
.el-card .el-card__task--primary {
  display: -webkit-box;
  display: -ms-flexbox;
  display: flex;
}

.el-card .el-card--primary {
  display: -webkit-box;
  display: -ms-flexbox;
  display: flex;
}

  • @mixin spec-selector($specSelector: '', $element: $E, $modifier: false, $block: $B)
@mixin spec-selector($specSelector: '', $element: $E, $modifier: false, $block: $B) {
  $modifierCombo: '';

  @if $modifier {
    $modifierCombo: $modifier-separator + $modifier;
  }

  @at-root {
    #{&}#{$specSelector}.#{$block+$element-separator+$element+$modifierCombo} {
      @content
    }
  }
}

@include b(card) {
  border-radius: 4px;
  border: 1px solid #ebeef5;
  background-color: #fff;
  overflow: hidden;
  color: #303133;
  transition: 0.3s;

  @include e(footer) {
    //传入单个
    padding: 20px;
    
    @include spec-selector(
      $specSelector: "",
      $element: $E,
      $modifier: primary,
      $block: $B
    ) {
      display: flex;
    }
  }
}

//编译后
.mk-card {
  border-radius: 4px;
  border: 1px solid #ebeef5;
  background-color: #fff;
  overflow: hidden;
  color: #303133;
  -webkit-transition: 0.3s;
  transition: 0.3s;
}

.mk-card__footer {
  padding: 20px;
}

.mk-card__footer.mk-card__footer--primary {
  display: -webkit-box;
  display: -ms-flexbox;
  display: flex;
}

  • @mixin meb(modifier: false,*m**o**d**i**f**i**e**r*:*f**a**l**s**e*,element: E,*E*,block: $B)
@mixin meb($modifier: false, $element: $E, $block: $B) {
  $selector: &;
  $modifierCombo: '';

  @if $modifier {
    $modifierCombo: $modifier-separator + $modifier;
  }

  @at-root {
    #{$selector} {
      .#{$block+$element-separator+$element+$modifierCombo} {
        @content
      }
    }
  }
}

@include b(card) {
  border-radius: 4px;
  border: 1px solid #ebeef5;
  background-color: #fff;
  overflow: hidden;
  color: #303133;
  transition: 0.3s;

  @include e(footer) {
    //传入单个
    padding: 20px;
    
   @include meb($modifier: primary) {
      display: flex;
    }
  }
}

//编译后
.mk-card {
  border-radius: 4px;
  border: 1px solid #ebeef5;
  background-color: #fff;
  overflow: hidden;
  color: #303133;
  -webkit-transition: 0.3s;
  transition: 0.3s;
}

.mk-card__footer {
  padding: 20px;
}
.mk-card__footer .mk-card__footer--primary {
  display: -webkit-box;
  display: -ms-flexbox;
  display: flex;
}

  • @mixin when($state)
    • 定义一些状态
@mixin when($state) {
  @at-root {
    &.#{$state-prefix + $state} {
      @content;
    }
  }
}

@include when(active) {
  color: red;
}

//编译后
.is-active {
  color: red;
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值