Сокращение повторяющегося кода в функциях Sass
Я работаю над образцом 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.
Затем эти функции вызываются в нескольких миксинах, например:
// 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().
Есть ли способ сделать код функции более элегантным и максимально сухим?
Я ценю любые идеи. Ура!
2 ответа
Я попытался написать универсальную функцию, которая получает имя карты в качестве параметра, но я не могу использовать интерполяцию в 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);
}
Вы можете создать высоту строки и размер шрифта в виде пар ключ / значение во вложенной карте и использовать интерполяцию для вывода свойства в цикле @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!