好的,所以我正在开发一个自定义的 scss 框架,并且我试图使所有预定义的变量都可以由用户轻松配置,但是由于 css 的工作方式,我需要在某些配置中反转某个变量,以便它们以正确的方式相互覆盖。现在我的变量配置如下:
$order-direction: 'ascending' !default;
$order: null !default;
$1: '1' !default;
$2: '2' !default;
$3: '3' !default;
@if $order-direction == 'ascending' {
$order:(
"1":$1,
"2":$2,
"3":$3
);
}
@if $order-direction != 'ascending' {
$order:(
"3":$3,
"2":$2,
"1":$1
);
}
这可行,但它使得我无法更改变量的名称(我稍后会在我的 css 类名中引用它),并且也使得我无法在之后添加更多内容。我想做的是使用一个变量,如果我改变顺序方向,该变量就会反转,如下所示:
$order-direction: 'ascending' !default;
$order: null !default;
$numbers:(
"1":1,
"2":2,
"3":3
) !default;
@function reverse($v){
$r: null;
@for 1 through length($numbers){
something that makes $r = reverse of $v
};
@return $r
};
@if $order-direction == 'ascending' {
$order: $numbers;
};
@if $order-direction != 'ascending' {
$order: reverse($numbers);
};
如果我能让这个工作,我可以让用户重新定义 $numbers 和 $order-direction 变量来设置所有相应的逻辑,而不是每个 $1、$2...等以及 $order-direction单独变量。此更改允许我使用标准的 @each $key, $value{} 运算符来创建类名称,用户可以更改派生类的名称和数量。
但是,我不知道如何根据数字从 sass 变量中提取某些内容,就像在 .js 中那样(类似于numbers[i])。我知道你可以使用 sass map 在对象中查找某些内容,例如 .js 字典查找,但我想不出一种方法可以像在 sass 中那样工作。
想法?
(P.S.我可能在某个地方漏掉了分号或逗号,我完全清楚,但我用不同的名称重新输入了这个,以便让它更有意义)
就像我说的,我的代码当前正在运行,但用户无法扩展。我试图找到一种使用 @map 的方法,但为了实现这一点,我需要保持名称相同,并且用户仍然无法向 $numbers 添加更多内容以供我的 sass 评估。
好吧,我做了很多挖掘,找到了一种方法来做到这一点,但这需要几个步骤。首先让我们看一下我发布的示例:
$order-direction: 'ascending' !default;
$order: null !default;
$numbers:(
"1":1,
"2":2,
"3":3
) !default;
@function reverse($v){
$r: null;
@for 1 through length($numbers){
something that makes $r = reverse of $v
};
@return $r
};
@if $order-direction == 'ascending' {
$order: $numbers;
};
@if $order-direction != 'ascending' {
$order: reverse($numbers);
};
我们保持定义的变量不变,然后函数需要执行几个步骤。首先,我们获取变量映射并将其转换为 2 个列表,一个用于名称,一个用于值:
@function reverse($val){
$names: null;
$values: null;
@each $n, $v in $val{
$names: append($names, $n);
$values: append($values, $v);
};
....
现在我们有一组 2 个原始列表,一个包含名称,另一个包含值。将变量分配给它们自己也很重要,因为 sass 不会使用append()动态更新变量。现在我们必须再次将它们重新组合成地图,我们这样做:
@for $i from 1 through length($names){
$r: map.set( $r, list.nth($names, ($i * -1) ), list.nth($values, ($i * -1) ));
};
@return $r;
};
完成此操作后,我们将从最后一个到第一个的列表组合成一个新的映射变量。由于我们同时使用了地图和列表,因此我们还需要适当的@use,因此我们将这两者都包含在内,然后我们得到:
@use "sass:map";
@use 'sass:list';
$order-direction: 'ascending' !default;
$order: null !default;
$numbers:(
"1":1,
"2":2,
"3":3
) !default;
@function reverse($val){
$names: null;
$values: null;
@each $n, $v in $val{
$names: append($names, $n);
$values: append($values, $v);
};
@for $i from 1 through length($names){
$r: map.set( $r, list.nth($names, ($i * -1) ), list.nth($values, ($i * -1) ));
};
@return $r;
};
@if $order-direction == 'ascending' {
$order: $numbers;
};
@if $order-direction != 'ascending' {
$order: reverse($numbers);
};
使用此配置,当变量 $order 设置为“升序”时,我们会得到一个 $numbers 变量,其值为 1,2,3,当它不是“升序”时,我们会得到 3,2,1。这对于在 css 中安排覆盖非常有用,因为应用了 css 中的最新类。对于我的用例,我使用它来更改断点的行为,以使用 min-width 或 max-width 来确定其 @media 规则,并且如果用户想要更改该功能(可能更像引导程序,但向后)可能是)现在就像翻转单个变量一样简单。但我不知道我的答案是否是最有效的。