建立一个字符串,这取决于可变数量的参数

Building of a string, which depends on variable number of parameters

我的问题是:如何在 Less 中构建一个字符串,这取决于可变数量的参数。例如,我想做一个 mixin,它可以帮助我编写 @font-face CSS 规则。所以我需要为我的字体的任意数量的格式(.eot、.ttf、.oft、.woff、.woff2、.svg)构建 src:... 字体 属性。这是我处理列表中所有字体格式的 Less 循环:

// @some-types - it is my font formats list, just smth. like 'otf', 'eot',...
// @old-src-value - it is string with src for my font from previous loop
// @counter - it is my loop counter 

.make-font-src(@some-types; @old-src-value; @counter) when (@counter <= length(@some-types)) {

    // Here we get next font format from @some-types
    @font-type: extract(@some-types, @counter);

    // Used for building 'format("opentype")' - like part of src value string
    .get-font-format(@font-type);

    // Building a part of src value string for this iteration
    @src-value: e('@{old-src-value}, url("@{font-path}@{font-filename}.@{font-type}") format("@{font-format}")');

    // Recursive call of this mixin for looping
    .make-font-src(@some-types; @src-value; (@counter + 1));
}

所以我被困在如何获取完整的 src 值字符串,当所有字体格式都将在循环中处理时?另请参考this codepen demo.

如我的评论所述,这不会导致递归定义错误,因为您已将值分配给不同的变量然后使用它。但是,Less 似乎在循环的第一次迭代完成后立即处理 属性-value 设置行。您可以通过将第一次迭代本身的 counter 值更改为 2 或更多来验证这一点。

一个解决方案(在我看来是解决问题的更好方法)是使用 property merging with comma 功能并直接设置 属性-value 对,如下面的代码片段所示:

.make-font-src(@some-types; @counter) when (@counter <= length(@some-types)) {
  @font-path: 'some/test/path/';
  @font-filename: 'Arial';
  @font-type: extract(@some-types, @counter);
  src+: e('url("@{font-path}@{font-filename}.@{font-type}") format("@{font-type}")');
  .make-font-src(@some-types; (@counter + 1));
}
div.test {
  .make-font-src('eot', 'woff', 'svg'; 1);
}

这在编译时会产生以下输出:

div.test {
  src: url("some/test/path/Arial.eot") format("eot"), 
       url("some/test/path/Arial.woff") format("woff"),
       url("some/test/path/Arial.svg") format("svg");
}

最后,我找到了自己的解决方案:如果我们添加带有保护的特殊 'getter' 混入,它会在循环的最后一次迭代中触发,我们可以从循环混入中获得完整的 src 值。

.getter(@cond; @list) when (@cond = length(@list)) {
    @font-src-full: @src-value;
}

这是一个fiddle with demo