在LESS中构建可变混合

时间:2013-08-09 15:06:06

标签: css less

我正在尝试在LESS中制作一个可变混音。为此,我对mixin使用以下语法:

.mixin (@a; @rest...) {
    // @rest is bound to arguments after @a   
    // @arguments is bound to all arguments 
}

但我不知道如何操纵@rest并阅读mixin的最后一个参数。

这是我的代码:

.color () { }

.color (@shade) {
    #id {
        background-color : rgb(@shade, @shade, @shade);
    }
}

.color (@shade, @rest...) {
    #id {
        background-color : rgb(@shade, @shade, @shade);
    }
    .color(@rest);
}

.color(200, 160);

正如您猜测的那样,这个mixin应该检查整个参数列表,并使用与mixin的最后一个参数相对应的灰色阴影为我的<div id="id">的背景着色(在这种情况下,rgb(160, 160,160))。

但是当我使用less-1.4.1.js编译此代码时,我收到以下错误:

SyntaxError: error evaluating function `rgb`: 
color functions take numbers as parameters

那么如何访问mixin的第二,第三,第四......参数?

非常感谢你的建议,周末愉快!


修改

This效果很好,非常感谢!

但是我想问另一个问题。假设我的mixin是可变参数,它需要至少一个与其余参数无关的参数(例如字符串或其他数字),但必须进行处理,以便可能调用以前的mixin可能是:

.color("first argument", 200, 160);
.color(-42, 200, 160);
.color(3, 200, 160); // 3 doesn't need to be processed in the loop

换句话说,.loop应该从第二个参数开始检查mixin的所有参数,并对第一个参数应用不同的过程。所以我需要将mixin的骨架改成这样的东西:

.color(...) {
   ...; // Handling the first parameter
   .loop (@arguments); // Handling the rest of the parameters
}

但在您的解决方案中,变量@arguments包含整个参数列表,包括第一个参数。如何在不在isnumber()上播放的情况下将其从列表中排除?

我确切地说,实际上在我的项目中,处理从第二个开始的每个参数,以便:

.loop(@list, @index: 1, @shade: NULL) when not (isnumber(@list)) and (isnumber(extract(@list, @index))) {
   .loop(@list, (@index + 1), extract(@list, @index));
}

变为

.loop(@list, @index: 1, @shade: NULL) when not (isnumber(@list)) and (isnumber(extract(@list, @index))) {
   .loop(@shade);
   .loop(@list, (@index + 1), extract(@list, @index));
}

并且此过程不仅仅是更改固定<div>的背景颜色;)但我想简化我的问题。

非常感谢您的回答和宝贵意见!


再次

编辑:你对我推荐的作品非常完美,马丁。再次感谢!

1 个答案:

答案 0 :(得分:2)

Less会与你的第二个和第三个.color mixin混淆,因为它们都可以只接受一个参数,并且@rest作为参数传递给mixin而不是数字(即列表)或空)它会导致更多问题。另外@rest......对于具有相同名称的多个mixin来说很棘手 - 最好将参数传递给另一组mixin(作为单个参数的列表)然后使用警卫在它们之间切换或者他们可以采取的论点数量。

我会以不同的方式构造mixins(并添加一个帮助mixin .loop,根据传递给.color的内容进行循环。

然后两个mixin就会这样工作:

  • .color:将@arguments中的所有参数传递给mixin .loop中的单个参数
    • .loop:如果参数既不是列表也不是数值 - &gt;没有输出
    • .loop:如果列表中有多个参数 - &gt;循环遍历列表,直到到达最后一个数字值(或者更确切地说当它遇到第一个非数字参数时停止)
    • .loop:根据其值
    • 到达最后一个参数返回输出时
    • .loop:if参数是单个值 - &gt;基于单个参数
    • 返回输出

Less 中可以这样做:

.loop(@list, @index: 1, @shade: NULL) when not (isnumber(@list)) and not (isnumber(extract(@list, @index))) and not (isnumber(@shade)) {}

.loop(@list, @index: 1, @shade: NULL) when not (isnumber(@list)) and (isnumber(extract(@list, @index))) {
   .loop(@list, (@index + 1), extract(@list, @index));
}

.loop(@list, @index: 1, @shade) when not (isnumber(@list)) and not (isnumber(extract(@list, @index))) {
    .loop(@shade);
}

.loop(@shade) when (isnumber(@shade)){
    #id {
        background-color: rgb(@shade, @shade, @shade);
    }
}

.color (...) {
    .loop(@arguments);
}

如果你现在打电话是这样的话:

.color(120,160);

输出 CSS 将如下所示:

#id {
  background-color: #a0a0a0;
}

对应于最后一个参数的值 - &gt; rgb(160,160,160)

现在只有列表中最后一个参数的输出。如果你想为每个参数做一些事情,你可以在第二个.loop mixin(实际循环)中这样做,并且可以去掉第三个仅用于将最后一个迭代步骤与其余部分分开的步骤。循环。


编辑:

对于您的其他问题“如何处理某些参数以及当它们不是数字时该怎么做?” - &gt;一般答案:您可以随时调整防护装置,并为特定情况添加额外的混合装置。

例如,如果您想使用.loop以不同方式处理第一个参数(或任何参数),则可以添加额外的.loop mixin - 如下所示:

.loop(@list) when not (isnumber(@list)) {
   /* do something with the first argument */
   @first_argument: extract(@list, 1);
   /* start the loop at the second argument:*/
   .loop(@list, 2);
}

其余部分保持原样,这应该做你想要的:

  • 将您的"first argument"@arguments保存到变量中(或者您可以随意使用它)
  • 在第二个参数处启动循环并继续直到它到达最后一个数字参数(如上所示)

如前所述,这只是一个例子,说明如何做你所要求的......但是你必须使用它并根据你想要的结果和你的具体问题设计防护和混合。

在循环中你可以对每个参数做一些事情......你可以对数字和非数字参数做不同的事情(你只需要调整守卫中的条件),你也可以检查参数是否有特定的单位等等。所有这一切都很简单,因为您只是使用extract()函数迭代列表并包含@index变量。

如果第一个参数/第一个参数具有特定的赋值,您可以使用@rest,就像我使用@arguments一样,并使用{{1}中已有的第一个参数执行某些操作在将.color发送到@rest之前1}} mixin。你会做这样的事情:

.loop