在Less中循环遍历变量名数组

57

我们的应用程序中,有一个预设颜色列表供用户选择,与该用户相关的所有内容都将具有该颜色。

在整个应用程序中,我们将使用带有颜色附加为类名的各种模块。

例如:

<div class="example_module green">
  ...
</div>

我们在使用LESS来编写CSS。

在很多地方,我们都会像这样做:

.example_module.green { background: @green; }
.example_module.red { background: @red; }
.example_module.blue { background: @blue; }
etc

我希望能够将所有这些颜色名称设置为一个数组并进行迭代。如果我们将来添加颜色,只需在一个地方添加即可。

伪代码:

@colors: ['green', 'red', 'blue'];

for each @color in @colors {
  .example_module.@color { background: @color; }
} 

LESS是否支持类似这样的东西?


使用递归在LESS中也是可能的。但在SASS中更加直接简单。或许你听说过Google? ;^) - Stephen Thomas
2
SASS 不是出路。我理解为什么它看起来更容易,但从长远来看,LESS 或 LESS 的分支将纯粹基于语法的遵循而获胜。 - augurone
4个回答

88

参见循环。 例如(假设@green@red@blue变量在其他地方已定义):

@colors: green, red, blue;

.example_module {
    .-(@i: length(@colors)) when (@i > 0) {
        @name: extract(@colors, @i);
        &.@{name} {background: @@name}
        .-((@i - 1));
    } .-;
}

- - -

使用Lists插件可以使现代Less编写更加简单明了:

@colors: green, red, blue;

.for-each(@name in @colors) {
    .example_module.@{name} {
        background: @@name;
    }
}

- - -

在Legacy Less中,可以使用以下语法糖:

@import "for";

@colors: green, red, blue;

.example_module {
    .for(@colors); .-each(@name) {
        &.@{name} {background: @@name}
    }
}

可以在此处找到导入的"for"代码片段(它只是递归Less循环的包装器混合)。还有一些例子在这里这里


2
common.less 第6行第3列出现了语法错误:无效类型的操作。6 .for(@colors); .-each(@color) { 7 @name: e(@color);由 lessc 1.7.5 提供。 - seyed
@seven-phases-max 感谢您的澄清。您知道在for循环中是否可以使用像lighten和darken这样的函数吗?您有任何示例吗? - Fab
@seven-phases-max,这在Less 2.6.1上不起作用。你有什么想法为什么会这样吗? - Morgan Feeney
@Morgan,我在2.6.1中没有遇到任何问题,所以我认为你需要创建一个新的工单(因为问题出在其他地方)。 - seven-phases-max
嗨@seven-phases-max,请看一下我刚发布的这个问题:http://stackoverflow.com/questions/36352716/passing-a-variable-list-through-for-loop-using-less-2-6-1-is-unable-to-compile - Morgan Feeney
显示剩余9条评论

17

这个mixin对我来说很有效。第二个参数是一个代码块,可以访问当前迭代元素(@value)和索引(@i)。

  1. 定义mixin:

  2. .for(@list, @code) {
        & {
            .loop(@i:1) when (@i =< length(@list)) {
                @value: extract(@list, @i);
    
                @code();
    
                .loop(@i + 1);
            }
    
            .loop();
        }
    }
    
  3. 使用:

    @colors: #1abc9c, #2ecc71, #3498db, #9b59b6;
    
    .for(@colors, {
        .color-@{i} {
            color: @value;
        }
    });
    
  4. 结果css:

  5. .color-1 {
      color: #1abc9c;
    }
    .color-2 {
      color: #2ecc71;
    }
    .color-3 {
      color: #3498db;
    }
    .color-4 {
      color: #9b59b6;
    }
    

因为这不是问题的答案,所以我要给你点个踩。你需要修改你的示例以匹配问题,或者找到一个更适合你的mixin库示例的问题(有很多早期和更一般的“如何循环”问题)。 - seven-phases-max
请注意,自从2014年2月27日Less添加了DR功能以来,就已经制作了基于DR的.for-each实现。回答一个旧问题只是为了发布另一个混合库实现某些东西的链接可能并不总是一个好主意。(供您参考:12等。最后,请参见#2270,了解目前所有可能的语法糖技巧的摘要。) - seven-phases-max

13

使用现代 LESS(>=3.7),您可以使用内置的each函数:

/* (assuming @clr-green, @clr-red, @clr-blue variables are defined elsewhere) */
@colors: {
  green: @clr-green;
  red: @clr-red;
  blue: @clr-blue;
}

each(@colors, {
  .example_module.@{key} {
    background: @value;
  }
});

您的回答,添加 @index 解决了我的问题。谢谢。 - Kunj
我在最新的文档中没有看到将对象传递给each()的能力。这个功能已经被弃用了吗? - Dana Woodman
1
@DanaWoodman 不是的。文档中就有,第二个例子。 - eyecatchUp
扶额,是啊,我现在看到了,不知道怎么错过了。别理我 ;) - Dana Woodman

0
  1. 定义混入(mixin):
.foreach(@list, @body, @i: length(@list)) when (@i>0) 
{
    .foreach(@list, @body, @i - 1);

    @n: length(@list);
    @value: extract(@list, @i);
    @body();
    /* you can use @value, @i, @n in the body */
}
  • 使用方法:

  • .example-module {
      .foreach (red green blue,
      {
        &.@{value} {
          color: @value;
        }
      });
    }
    

    另一个例子:

    .nth-child (@list, @style) {
        .foreach(@list, 
        {
          @formula: e(%("%dn+%d", @n, @i));
          &:nth-child(@{formula}) {
            @style();
          }
        });
    }
    
    tr {
      .nth-child (#bbb #ccc #ddd #eee,
      {
          background: @value;
      });
    }
    

    网页内容由stack overflow 提供, 点击上面的
    可以查看英文原文,
    原文链接