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>