减少 Sass 函数中的重复代码
Cutting down repeating code in Sass functions
我正在开发一个 HTML 样板,它使用大量 Sass 来创建可维护且易于使用的代码库。其中一部分是一些功能:
// Returns the scale value found at $key.
@function get-type-scale($key) {
$value: map-get($type-scale, $key);
@if $value != null {
@return $value;
}
@else {
@warn "Unfortunately, `#{$key}` is not defined in the `$type-scale` map.";
}
}
// Returns the line-height value found at $key.
@function get-line-height($key) {
$value: map-get($line-heights, $key);
@if $value != null {
@return $value;
}
@else {
@warn "Unfortunately, `#{$key}` is not defined in the `$line-heights` map.";
}
}
// etc... I have 2 more functions like this where only the $map changes.
这些函数随后会在一些 mixin 中被调用,如下所示:
// Sets font-size and line-height based on the $level.
@mixin set-type($level: 0) {
font-size: get-type-scale($level);
line-height: get-line-height($level);
}
虽然这工作得很好,但我不喜欢我在函数中重复大量代码的事实。我已经尝试编写一个接收地图名称作为参数的通用函数,但我无法在 map-get() 中使用插值。
有没有办法让函数代码更优雅,尽可能DRY?
我很感激任何见解。干杯!
I've tried writing a generic function that receives a map name as a parameter, but I cannot use interpolation in map-get().
不幸的是,根本不可能从其他变量的名称创建变量名(只能从它的值)。此外,变量只知道它的值而不是它的名称,这是我们在定义变量警告消息时面临的另一个问题。
我提出了一些改进,减少了重复代码的数量并保持了高级函数调用的易用性。必须将第三个变量传递给泛型函数的批评是有道理的,但我就是找不到一种干净的方法来避免它。
$line-heights: (
0: 1em,
1: 2em
);
$type-scale: (
0: 1em,
1: 2em
);
// Returns the scale value found at $key.
@function get-type-scale($key) {
@return get-value-or-warn($type-scale, $key, 'type-scale');
}
// Returns the line-height value found at $key.
@function get-line-height($key) {
@return get-value-or-warn($line-heights, $key, 'line-heights');
}
@function get-value-or-warn($map, $key, $map-name) {
$value: map-get($map, $key);
@if $value != null {
@return $value;
}
@else {
@warn "Unfortunately, `#{$key}` is not defined in the `$#{$map-name}` map.";
}
}
// Sets font-size and line-height based on the $level.
@mixin set-type($level: 0) {
font-size: get-type-scale($level);
line-height: get-line-height($level);
}
您可以在嵌套映射中将行高和字体大小创建为 key/value 对,并使用插值在 @each 循环中打印出 属性 – 如:
$map:(
0 : (line-height: 1.3, font-size: 16px),
1 : (line-height: 1.3, font-size: 17px),
2 : (line-height: 1.3, font-size: 18px),
3 : (line-height: 1.4, font-size: 19px),
4 : (line-height: 1.5, font-size: 20px)
);
@mixin set-type($level: 0){
$found: map-get($map, $level);
@if not $found { @warn 'Key `#{$level}` not found in $map!'; }
@else { @each $prop, $value in $found { #{$prop} : $value; } }
}
.class { @include set-type(1); } // line-height: 1.3; font-size: 17px;
.class { @include set-type(5); } // WARN: Key `5` not found in $map!
我正在开发一个 HTML 样板,它使用大量 Sass 来创建可维护且易于使用的代码库。其中一部分是一些功能:
// Returns the scale value found at $key.
@function get-type-scale($key) {
$value: map-get($type-scale, $key);
@if $value != null {
@return $value;
}
@else {
@warn "Unfortunately, `#{$key}` is not defined in the `$type-scale` map.";
}
}
// Returns the line-height value found at $key.
@function get-line-height($key) {
$value: map-get($line-heights, $key);
@if $value != null {
@return $value;
}
@else {
@warn "Unfortunately, `#{$key}` is not defined in the `$line-heights` map.";
}
}
// etc... I have 2 more functions like this where only the $map changes.
这些函数随后会在一些 mixin 中被调用,如下所示:
// Sets font-size and line-height based on the $level.
@mixin set-type($level: 0) {
font-size: get-type-scale($level);
line-height: get-line-height($level);
}
虽然这工作得很好,但我不喜欢我在函数中重复大量代码的事实。我已经尝试编写一个接收地图名称作为参数的通用函数,但我无法在 map-get() 中使用插值。
有没有办法让函数代码更优雅,尽可能DRY?
我很感激任何见解。干杯!
I've tried writing a generic function that receives a map name as a parameter, but I cannot use interpolation in map-get().
不幸的是,根本不可能从其他变量的名称创建变量名(只能从它的值)。此外,变量只知道它的值而不是它的名称,这是我们在定义变量警告消息时面临的另一个问题。
我提出了一些改进,减少了重复代码的数量并保持了高级函数调用的易用性。必须将第三个变量传递给泛型函数的批评是有道理的,但我就是找不到一种干净的方法来避免它。
$line-heights: (
0: 1em,
1: 2em
);
$type-scale: (
0: 1em,
1: 2em
);
// Returns the scale value found at $key.
@function get-type-scale($key) {
@return get-value-or-warn($type-scale, $key, 'type-scale');
}
// Returns the line-height value found at $key.
@function get-line-height($key) {
@return get-value-or-warn($line-heights, $key, 'line-heights');
}
@function get-value-or-warn($map, $key, $map-name) {
$value: map-get($map, $key);
@if $value != null {
@return $value;
}
@else {
@warn "Unfortunately, `#{$key}` is not defined in the `$#{$map-name}` map.";
}
}
// Sets font-size and line-height based on the $level.
@mixin set-type($level: 0) {
font-size: get-type-scale($level);
line-height: get-line-height($level);
}
您可以在嵌套映射中将行高和字体大小创建为 key/value 对,并使用插值在 @each 循环中打印出 属性 – 如:
$map:(
0 : (line-height: 1.3, font-size: 16px),
1 : (line-height: 1.3, font-size: 17px),
2 : (line-height: 1.3, font-size: 18px),
3 : (line-height: 1.4, font-size: 19px),
4 : (line-height: 1.5, font-size: 20px)
);
@mixin set-type($level: 0){
$found: map-get($map, $level);
@if not $found { @warn 'Key `#{$level}` not found in $map!'; }
@else { @each $prop, $value in $found { #{$prop} : $value; } }
}
.class { @include set-type(1); } // line-height: 1.3; font-size: 17px;
.class { @include set-type(5); } // WARN: Key `5` not found in $map!