您的位置:首页 > 汽车 > 新车 > element ui中的scss语法理解

element ui中的scss语法理解

2024/7/3 17:51:12 来源:https://blog.csdn.net/song854601134/article/details/140098888  浏览:    关键词:element ui中的scss语法理解

摘录至

导读

首先来看一个bem命名示例

.el-message-box{}
.el-message-box__header{}
.el-message-box__header--active{}

如果使用已经封装好的bem方法的话,那么可以写成

@include b('message-box') {@include e('header') {@include m('active');}
}

接下来我们来看一下bem方法是如何实现的

bem方法解析

首先我们找到style/mixins/config.scss文件,里面定义了如下几个变量

$namespace: 'el';
$element-separator: '__';
$modifier-separator: '--';
$state-prefix: 'is-';

然后我们再找到style/mixins/config.scss文件,找到b,e,m方法

/* BEM-------------------------- */
@mixin b($block) {$B: $namespace+'-'+$block !global;.#{$B} {@content;}
}
@mixin e($element) {$E: $element !global;$selector: &;$currentSelector: "";@each $unit in $element {$currentSelector: #{$currentSelector + "." + $B + $element-separator + $unit + ","};}@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 变量提升,将局部变量提升为全局变量,在其他函数体内也能访问到此变量
+ @at-root将父级选择器直接暴力的改成根选择器

.header{@at-root {.content{color:red}}
}

编译为

.header{}
.content{color:red}

+ #{}插值,可以通过 #{} 插值语法在选择器和属性名中使用 SassScript 变量

$name: foo;
$attr: border;
p.#{$name} {#{$attr}-color: blue;
}

编译为

p.foo {border-color: blue;
}

在大多数情况下,这种做可能还不如使用直接变量来的方便,但使用 #{}意味着靠近它的运算符都将被视为纯CSS

p {$font-size: 12px;$line-height: 30px;font: #{$font-size}/#{$line-height};
}

编译为

p.foo {font:12px/30px;
}

现在我们在重新看一下b方法,定义了一个全局变量,拼接了一下字符串,逻辑很简单,e方法稍微复杂点,调用了一个hitAllSpecialNestRule方法(判断父级选择器是否包含'--','is',':'),hitAllSpecialNestRule定义在style/mixins/function文件中,代码如下:

@import 'config';
/* BEM support Func-------------------------- */
// inspect Returns a string representation of $value
//@debug inspect("Helvetica"); unquote('"Helvetica"')
@function selectorToString($selector) {$selector: inspect($selector);$selector: str-slice($selector, 2, -2);@return $selector;
}
// 判断选择器(.el-button__body--active) 是否包含 '--'
@function containsModifier($selector) {$selector: selectorToString($selector);@if str-index($selector, $modifier-separator) {@return true;} @else {@return false;}
}
// 判断选择器(.el-button__body.is-active) 是否包含 'is'
@function containWhenFlag($selector) {$selector: selectorToString($selector);@if str-index($selector, '.' + $state-prefix) {@return true;} @else {@return false;}
}
//  判断选择器(.el-button__body:before) 是否包含伪元素(:hover)
@function containPseudoClass($selector) {$selector: selectorToString($selector);@if str-index($selector, ':') {@return true;} @else {@return false;}
}
// hit:命中 nest:嵌套
@function hitAllSpecialNestRule($selector) {@return containsModifier($selector) or containWhenFlag($selector) or containPseudoClass($selector);
}

inspect:以字符串的形式返回表达式

@debug meta.inspect(10px 20px 30px); // unquote("10px 20px 30px")
@debug meta.inspect(("width": 200px)); // unquote('("width": 200px)')
@debug meta.inspect(null); // unquote("null")
@debug meta.inspect("Helvetica"); // unquote('"Helvetica"')

Maps不能转换为纯CSS。作为变量的值或参数传递给CSS函数将会导致错误。使用inspect($value) 函数以产生输出字符串,这对于调试 maps 非常有用。
重新回到e方法中,也是先拼字符串,然后再判断父级class是否存在嵌套关系,然后输出结果。

.container {@include b('button') {width: 200px;height: 200px;@include e('body') {color: #ccc;}}
}
.container--fix {@include b('button') {width: 200px;height: 200px;@include e('body') {color: #ccc;}}
}

编译为

.container .el-button {width: 200px;height: 200px;
}
.el-button__body {color: #ccc;
}
.container--fix .el-button {width: 200px;height: 200px;
}
.container--fix .el-button .el-button__body {color: #ccc;
}

最后一个e方法,流程和b一致,区别在拼接currentSelector字符串时,使用了$父级选择器,还没有使用全局变量B+全局变量E来拼接,因为结构不一定是B-E-M,有可能是B-M。最后附上完整的编译结果

.container {@include b('button') {width: 200px;height: 200px;@include e('body') {color: #ccc;@include m('success');}}
}
.container--fix {@include b('button') {width: 200px;height: 200px;@include e('body') {color: #ccc;@include m('success');}}
}

编译为

.container .el-button {width: 200px;height: 200px;
}
.el-button__body {color: #ccc;
}
.container--fix .el-button {width: 200px;height: 200px;
}
.container--fix .el-button .el-button__body {color: #ccc;
}

scss完整代码如下,可以在scss在线编译
中编译调试

$namespace: 'el';
$element-separator: '__';
$modifier-separator: '--';
$state-prefix: 'is-';
@function selectorToString($selector) {$selector: inspect($selector);$selector: str-slice($selector, 2, -2);@return $selector;
}
// 判断选择器(.el-button__body--active) 是否包含 '--'
@function containsModifier($selector) {$selector: selectorToString($selector);@if str-index($selector, $modifier-separator) {@return true;} @else {@return false;}
}
// 判断选择器(.el-button__body.is-active) 是否包含 'is'
@function containWhenFlag($selector) {$selector: selectorToString($selector);@if str-index($selector, '.' + $state-prefix) {@return true;} @else {@return false;

发现有许多 sass 快速入门中没有提到过的语法: @if@else 等等,这里查阅具体文档列出其功能:

  • @if @else 这两者和任何编程语言的 if … else … 的用法是一样的,条件判断。if 中条件为 true 进入逻辑,否则使用 else 逻辑。
  • @at-root @at-root 指令导致一个或多个规则被限定输出在文档的根层级上,而不是被嵌套在其父选择器下。
  • @content 样式内容块可以传递到混入(mixin)包含样式的位置。样式内容块将出现在混入内的任何 @content 指令的位置。这使得可以定义抽象 关联到选择器和指令的解析。
  • @each in 类似js用法,遍历列表获取每个value值。
  • #{...} 是插值语法,用于在选择器和属性名中使用 SassScript 变量,所以 .#{$B} 表达式,如果 $B 的值为 hello-world,那么表达式结果等于 .hello-world

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com