scss: map:merge 和 @each $attribute, $value in $variables

研究 Element-plus 源码时,有以下一段代码:

less 复制代码
// 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


swift 复制代码
// 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 混合名的示例:

swift 复制代码
@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 变量与组件关联起来。例如,我们可以使用这段代码为按钮组件设置默认颜色、文字颜色和边框颜色。

具体来说,这段代码的执行步骤如下:

  1. 混合名会遍历 $variables 映射中的每个键值对。
  2. 如果键等于 "default",那么混合名会将组件的默认 CSS 变量设置为值。
  3. 否则,混合名会将组件的特定属性的 CSS 变量设置为值。

在示例代码中,$button-variables 映射包含三个键值对:

  • "default" 的值为 #fff,表示按钮组件的默认颜色。
  • "color" 的值为 #000,表示按钮组件的文字颜色。
  • "border-color" 的值为 #ddd,表示按钮组件的边框颜色。

因此,这段代码会将以下 CSS 变量设置为相应的值:

  • --button 的值为 #fff
  • --button-color 的值为 #000
  • --button-border-color 的值为 #ddd

sass 中 map 的用法

上边的仅仅是一个简单的示例。看源码过程中,我们可以找到 $button 的定义:

css 复制代码
// path: element-plus/packages/theme-chalk/src/common/var.scss
@use 'sass:map';$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)});}

解释一下这段代码的作用:

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 中实现灵活和可重用的样式。

相关推荐
拾光拾趣录10 分钟前
for..in 和 Object.keys 的区别:从“遍历对象属性的坑”说起
前端·javascript
OpenTiny社区20 分钟前
把 SearchBox 塞进项目,搜索转化率怒涨 400%?
前端·vue.js·github
编程猪猪侠1 小时前
Tailwind CSS 自定义工具类与主题配置指南
前端·css
qhd吴飞1 小时前
mybatis 差异更新法
java·前端·mybatis
YGY Webgis糕手之路1 小时前
OpenLayers 快速入门(九)Extent 介绍
前端·经验分享·笔记·vue·web
患得患失9491 小时前
【前端】【vueDevTools】使用 vueDevTools 插件并修改默认打开编辑器
前端·编辑器
ReturnTrue8681 小时前
Vue路由状态持久化方案,优雅实现记住表单历史搜索记录!
前端·vue.js
UncleKyrie1 小时前
一个浏览器插件帮你查看Figma设计稿代码图片和转码
前端
遂心_1 小时前
深入解析前后端分离中的 /api 设计:从路由到代理的完整指南
前端·javascript·api
你听得到112 小时前
Flutter - 手搓一个日历组件,集成单日选择、日期范围选择、国际化、农历和节气显示
前端·flutter·架构