bem

86 阅读1分钟

assets下新建config.scss,function.scss,mixins.scss

config.scss

/*
  config.scss 文件编写 BEM 的基础配置比如样式名前缀、元素、修饰符、状态前缀:
*/

$namespace: "el" !default; // 所有的组件以el开头,如 el-input
$common-separator: "-" !default; // 公共的连接符
$element-separator: "__" !default; // 元素以__分割,如 el-input__inner
$modifier-separator: "--" !default; // 修饰符以--分割,如 el-input--mini
$state-prefix: "is-" !default; // 状态以is-开头,如 is-disabled

function.scss

@use "config";

// 该函数将选择器转化为字符串,并截取指定位置的字符
@function selectorToString($selector) {
  $selector: inspect(
    $selector
  ); // inspect(...) 表达式中的内容如果是正常会返回对应的内容,如果发生错误则会弹出一个错误提示。
  $selector: str-slice($selector, 2, -2); // str-slice 截取指定字符
  @return $selector;
}
// 判断父级选择器是否包含'--'
@function containsModifier($selector) {
  $selector: selectorToString($selector);

  @if str-index($selector, config.$modifier-separator) {
    // str-index 返回字符串的第一个索引
    @return true;
  } @else {
    @return false;
  }
}
// 判断父级选择器是否包含'.is-'
@function containWhenFlag($selector) {
  $selector: selectorToString($selector);

  @if str-index($selector, "." + config.$state-prefix) {
    @return true;
  } @else {
    @return false;
  }
}
// 判断父级是否包含 ':' (用于判断伪类和伪元素)
@function containPseudoClass($selector) {
  $selector: selectorToString($selector);

  @if str-index($selector, ":") {
    @return true;
  } @else {
    @return false;
  }
}
// 判断父级选择器,是否包含`--` `.is-`  `:`这三种字符
@function hitAllSpecialNestRule($selector) {
  @return containsModifier($selector) or containWhenFlag($selector) or
    containPseudoClass($selector);
}

mixins.scss

// $B 表示定义一个一个变量,$namespace 是来自 config.scss 文件中定义的变量
// !global 表示其是一个全局变量,这样就可以在整个文件的任意地方使用。#{} 字符串插值,类似模板语法
// 通过 @content 可以将 include{} 中传递过来的内容导入到指定位置。
@import "./config.scss";
@import "./function.scss";

@mixin b($block) {
  $B: $namespace + "-" + $block !global;

  .#{$B} {
    @content;
  }
}

@mixin e($element) {
  $E: $element !global; //首先定义一个全局变量 $E
  $selector: &; //接着定义父选择器 $selector
  $currentSelector: ""; //再定义当前的选择器 $currentSelector
  // 再通过循环得到当前的选择器
  @each $unit in $element {
    // @debug $unit;
    $currentSelector: #{$currentSelector +
      "." +
      $B +
      $element-separator +
      $unit +
      ","};
  }

  @if hitAllSpecialNestRule($selector) {
    @at-root {
      #{$selector} {
        #{$currentSelector} {
          @content;
        }
      }
    }
  } @else {
    @at-root {
      @debug #{$currentSelector};
      #{$currentSelector} {
        @content;
      }
    }
  }
}

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

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

@mixin when($state) {
  @at-root {
    &.#{$state-prefix + $state} {
      @content;
    }
  }
}

ok,试一下效果

<template>
  <div class="el-block-box">
    王振炎
    <div class="el-block-box__item">
      哈哈
      <div class="el-block-box__item--success is-black">王振炎</div>
    </div>
  </div>
</template>

<style scoped lang="scss">
@import "@/mixins/mixins.scss";
@include b("block-box") {
  width: 500px;
  height: 500px;
  background-color: red;
  @include e("item") {
    width: 100px;
    height: 100px;
    background-color: blue;
    @include m("success") {
      background-color: green;
      width: 100px;
      height: 100px;
      @include when("black") {
        background-color: black;
      }
    }
  }
}
</style>

image.png