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;
}