scss: map:merge 和 @each $attribute, $value in $variables
研究 Element-plus 源码时,有以下一段代码:
css
// path: element-plus/packages/theme-chalk/src/button.scss
@include b(button) {
@include set-component-css-var('button', $button);
}
有关 b 的理解,以及 @include 的作用
set-component-css-var
css
// path: element-plus/packages/theme-chalk/src/mixins/_var.scss
@mixin set-component-css-var($name, $variables) {
@each $attribute, $value in $variables {
@if $attribute == 'default' {
#{getCssVarName($name)}: #{$value};
} @else {
#{getCssVarName($name, $attribute)}: #{$value};
} }}
这段代码定义了一个 Sass 混合名为 set-component-css-var
,它有两个参数:$name
和 $variables
。$name
参数是组件的名称,$variables
参数是一个 CSS 变量名到值的映射。
混合名会遍历 $variables
映射中的每个键值对。如果键等于 "default"
,那么混合名会将组件的默认 CSS 变量设置为值。否则,混合名会将组件的特定属性的 CSS 变量设置为值。
getCssVarName
函数用于生成 CSS 变量名。函数有两个参数:组件名称和可选的属性名称。如果未提供属性名称,则函数会返回组件的默认 CSS 变量名(例如,--button
)。否则,函数会返回包含组件名称和属性名称的 CSS 变量名(例如,--button-color
)。
以下是一个使用 set-component-css-var
混合名的示例:
css
@mixin set-component-css-var($name, $variables) {
@each $attribute, $value in $variables {
@if $attribute == 'default' {
#{getCssVarName($name)}: #{$value};
} @else {
#{getCssVarName($name, $attribute)}: #{$value};
}
}
}
$button-variables = (
"default": "#fff",
"color": "#000",
"border-color": "#ddd",
);
@include set-component-css-var("button", $button-variables);
上边代码生成什么了?
css
--button: #fff;
--button-color: #000;
--button-border-color: #ddd;
这段代码的用途是将 CSS 变量与组件关联起来。例如,我们可以使用这段代码为按钮组件设置默认颜色、文字颜色和边框颜色。
具体来说,这段代码的执行步骤如下:
- 混合名会遍历
$variables
映射中的每个键值对。 - 如果键等于
"default"
,那么混合名会将组件的默认 CSS 变量设置为值。 - 否则,混合名会将组件的特定属性的 CSS 变量设置为值。
在示例代码中,$button-variables
映射包含三个键值对:
"default"
的值为#fff
,表示按钮组件的默认颜色。"color"
的值为#000
,表示按钮组件的文字颜色。"border-color"
的值为#ddd
,表示按钮组件的边框颜色。
因此,这段代码会将以下 CSS 变量设置为相应的值:
--button
的值为#fff
。--button-color
的值为#000
。--button-border-color
的值为#ddd
。
sass 中 map 的用法
scss: map:merge 和 @each $attribute, $value in v a r i a b l e s 上边的仅仅是一个简单的示例。看源码过程中,我们可以找到 ' variables 上边的仅仅是一个简单的示例。看源码过程中,我们可以找到 ` variables上边的仅仅是一个简单的示例。看源码过程中,我们可以找到'button` 的定义:
css
// path: element-plus/packages/theme-chalk/src/common/var.scss
$button: () !default;
$button: map.merge(
(
'font-weight': getCssVar('font-weight-primary'),
'border-color': getCssVar('border-color'),
'bg-color': getCssVar('fill-color', 'blank'),
'text-color': getCssVar('text-color', 'regular'),
'disabled-text-color': getCssVar('disabled-text-color'),
'disabled-bg-color': getCssVar('fill-color', 'blank'),
'disabled-border-color': getCssVar('border-color-light'),
'divide-border-color': rgba($color-white, 0.5),
'hover-text-color': getCssVar('color-primary'),
'hover-bg-color': getCssVar('color-primary', 'light-9'),
'hover-border-color': getCssVar('color-primary-light-7'),
'active-text-color': getCssVar('button-hover-text-color'),
'active-border-color': getCssVar('color-primary'),
'active-bg-color': getCssVar('button', 'hover-bg-color'),
'outline-color': getCssVar('color-primary', 'light-5'),
'hover-link-text-color': getCssVar('color-info'),
'active-color': getCssVar('text-color', 'primary'),
),
$button
);
注意:要用 map 功能,你需要导入这个功能。以上代码片段第一行就是导入 map 函数
1. 定义变量:
- 代码首先定义了一个名为
$button
的变量,并将其默认值设置为空映射(() !default;
)。这意味着如果$button
变量此前没有被定义,它将会被初始化为一个空映射。
2. 合并映射:
-
代码接着使用了 Sass 内置的
map.merge
函数来合并两个映射:
- 第一个映射包含了一系列按钮样式属性的键值对,例如:
font-weight
: 字体粗细border-color
: 边框颜色bg-color
: 背景颜色text-color
: 文字颜色disabled-text-color
: 禁用状态下的文字颜色hover-text-color
: 鼠标悬停状态下的文字颜色active-text-color
: 鼠标按下状态下的文字颜色- ... 等等
- 这些键值对中的值都是通过
getCssVar
函数获取的 CSS 变量,这意味着这些样式属性的值可以被集中控制和调整。 - 第二个映射是
$button
变量本身。如果$button
变量已经被定义并包含了一些样式属性,那么这些属性将会被保留并与第一个映射中的属性进行合并。
- 第一个映射包含了一系列按钮样式属性的键值对,例如:
3. 最终结果:
- 经过
map.merge
函数的处理,$button
变量将会包含一个完整的按钮样式属性映射,其中的值都是 CSS 变量。 - 这意味着我们可以通过修改 CSS 变量的值来轻松调整按钮的整体样式,而无需逐一修改每个样式属性。
总结:
- 这段代码的目的在于使用 CSS 变量来定义按钮的样式,使样式管理更加灵活和统一。
- 通过使用
map.merge
函数,代码可以将默认的按钮样式属性与自定义的属性进行合并,保留了灵活性和可扩展性。
getCssVar 和 getCssVarName
在以上代码中用到了 getCssVar
和 getCssVarName
这两个函数,我统一解释一下,因为这两个函数都调用了 joinVarName
perl
// path: element-plus/packages/theme-chalk/src/mixins/function.scss
@function joinVarName($list) {
$name: '--' + config.$namespace;
@each $item in $list {
@if $item != '' {
$name: $name + '-' + $item;
}
}
@return $name;
}
// getCssVarName('button', 'text-color') => '--el-button-text-color'
@function getCssVarName($args...) {
@return joinVarName($args);
}
// getCssVar('button', 'text-color') => var(--el-button-text-color)
@function getCssVar($args...) {
@return var(#{joinVarName($args)});
}
#{}
插值,可以通过#{}
插值语法在选择器和属性名中使用SassScript
变量
解释一下这段代码的作用:
1. joinVarName
函数:
- 这个函数的作用是将一个列表(
$list
)中的所有元素连接起来,并在开头加上一个前缀(--
加上config.$namespace
),形成一个完整的 CSS 变量名。 - 它会遍历
$list
中的每个元素,如果元素不为空,则将其添加到$name
变量中,并在每个元素之间加上一个连字符(-
)。 - 最后,函数会返回生成的 CSS 变量名。
2. getCssVarName
函数:
- 这个函数是
joinVarName
函数的一个简便调用方式。它可以接受任意数量的参数($args...
),并将这些参数作为列表传递给joinVarName
函数。 - 它会返回
joinVarName
函数生成的 CSS 变量名。
举例说明:
- 调用
getCssVarName('button', 'text-color')
会返回--el-button-text-color
(假设config.$namespace
的值为el
)。 - 调用
getCssVarName('primary-color')
会返回--el-primary-color
。
代码的作用:
- 这段代码是为了方便地生成 CSS 变量名,并在生成的变量名中加入命名空间(
config.$namespace
)以避免变量名冲突。 - 这在大型项目中,尤其是使用了 CSS 预处理器的项目中,是非常有用的,可以帮助我们更好地管理 CSS 变量。
关于 getCssVar 解释两个点:$args... 和 var
在 Sass 中,$args...
表示一个可变参数列表。这意味着 args
变量可以接受任意数量的参数,这些参数可以是任意类型的值。
在 getCssVar
函数中,$args...
用于接收 CSS 变量名的参数列表。例如,调用 getCssVar('primary-color')
函数时,$args...
将包含一个元素,该元素的值为 'primary-color'
。
$args...
的使用可以使函数更加灵活,可以接受任意数量的参数。
以下是一些使用 $args...
的例子:
less
@function add($x, $y...) {
$total: $x;
@each $arg in $y {
$total: $total + $arg;
}
@return $total;
}
// 将两个数相加
$sum: add(1, 2, 3);
// 将三个字符串连接起来
$string: add('a', 'b', 'c');
在第一个示例中,add()
函数用于将两个或多个数相加。$args...
用于接收任意数量的数字参数。
在第二个示例中,add()
函数用于将三个字符串连接起来。$args...
用于接收任意数量的字符串参数。
为什么这里要解释一下 var ?
var 函数容易有歧义,因为在 css 中和 sass 中都有这个函数,他们的功能也是不一样的,因此在这做一个区分:简单来说,sass 中的 var 函数用来定义变量,CSS 中的 var 用来引用变量。
CSS 中的 var
在 CSS 中,var()
函数是 CSS custom properties 的语法,用于引用 CSS custom properties。
CSS custom properties 是 CSS 中的一个新特性,允许我们在 CSS 中定义自定义变量。
CSS custom properties 的语法如下:
ini
--[variable-name]: [value];
例如,以下 CSS 代码定义了一个名为 --color
的 CSS custom property,并将其值设置为 #fff
:
css
--color: #fff;
我们可以使用 var()
函数引用 CSS custom properties。例如,以下 CSS 代码将 .my-element
元素的颜色设置为 --color
变量的值:
css
.my-element {
color: var(--color);
}
在 Sass 中,var()
函数用于定义 CSS custom properties。因此,Sass 中的 var()
函数与 CSS 中的 var()
函数是相同的。
sass 中的 var
在 Sass 中,var()
函数用于定义 CSS 变量。
var()
函数的语法如下:
php
var($name, $value);
$name
是变量的名称,$value
是变量的值。
var()
函数会将 $name
变量定义为一个 CSS 变量,并将 $value
赋值给该变量。
以下是使用 var()
函数的例子:
css
$color: var(--color);
这段代码会定义一个名为 $color
的 CSS 变量,并将其值设置为 var(--color)
。
$color
变量可以被用于 CSS 中,例如:
css
.my-element {
color: $color;
}
这段 CSS 将会将 .my-element
元素的颜色设置为 var(--color)
变量的值。
var()
函数还可以用于定义具有默认值的 CSS 变量。例如:
css
$color: var(--color, #fff);
这段代码会定义一个名为 $color
的 CSS 变量,并将其值设置为 #fff
。如果 var(--color)
变量未定义,则将使用 #fff
作为其值。
var()
函数是 Sass 中定义 CSS 变量的重要工具。它可以帮助我们在 CSS 中实现灵活和可重用的样式。
@mixin与@include %与@extend @function
scss
@mixin 使用@include引用,可传参,返回一段css样式,不用会生成一个class,生成结果是直接拷贝,这样多处引用,会造成代码重复
% 使用@extend引用,不可传参,返回一段css样式。%开头的class只是用来extend,不会生成在代码里。生成后,多个class用逗号连接,提取成一个样式,减少重复代码.
@function与@mixin的最大不同,返回的是一个值,不是一段css样式
@forward与@use
css
@forward:
概念:@forward用于将模块的部分或全部内容重新导出,使其他模块可以通过@use导入该模块的内容。
@use:
概念:@use用于导入其他Scss或Sass模块,并创建一个命名空间来管理导入的模块中的变量、混合器、函数和样式规则。