Less css: 循环中循环的最大调用堆栈大小

Less css: Maximum call stack size with loop in loop

所以我想少构建我的网格。 我使用 less 页面 (http://lesscss.org/features/#loops-feature) 中描述的列方法。但是当我 运行 它时我得到一个错误。

Error: Maximum call stack size exceeded in file /assets/less/grid.less line no. 54

第 54 行是我启动循环的地方.loop(@grids, (@grids + 1));

如果我删除 mixin 中的 .generate-offset(@n, @tag, (@i + 1));,我会得到另一个错误。

Error: Cannot read property 'denominator' of undefined in file/assets/less/grid.less line no. 54

然而,当我 运行 手动混合时,我的工作就像一个魅力。 例如

.generate-columns(2, xs);
.generate-offset(2, xs);

如果我 运行 .loop mixin 没有 .generate-columns.generate-offset mixin 它也能正常工作并且 运行s 是预期的 3 倍(由于到 3 个断点)。

知道为什么我在结合两者时会出现这些错误吗?

@prefixes: 'sm', 'md', 'lg';
@breakpoints: '0', '100rem', '140rem';
@columns: '2','6','12';

.generate-offset(@n, @tag, @i: 1) when (@i < @n) {
  .offset--@{tag}-@{i} {
    margin-left: (@i * 100% / @n);
  }
  .generate-offset(@n, @tag, (@i + 1));
}

// Grid loops

.loop(@index, @count) when (@index > 0){
    // extract variables
    @current: (@count - @index);
    @prefix: e(extract(@prefixes, @current));
    @breakpoint: e(extract(@breakpoints, @current));
    @column: e(extract(@columns, @current));

    @media (min-width: @breakpoint) {
      .generate-columns(@column, @prefix);
      .generate-offset(@column, @prefix);
    }

    .loop ((@index - 1), @count);
}

// run
@grids: length(@breakpoints);
.loop(@grids, (@grids + 1));

解决方案:

以防万一有人遇到同样的问题,我的最终代码现在看起来像这样。

@prefixes: sm, md, lg;
@breakpoints: 0, 100rem, 140rem;
@columns: 2,6,12;
// ********************
// Column Mixin
//
.generate-columns(@n, @tag, @i: 1) when (@i =< @n) {
  .column--@{tag}-@{i} {
    flex: 0 0 (@i * 100% / @n);
  }
  .generate-columns(@n, @tag, (@i + 1));
}
// Offset Mixin
//
.generate-offset(@col, @tag, @i: 1) when (@i < @col) {
  .offset--@{tag}-@{i} {
    margin-left: (@i * 100% / @col);
  }
  .generate-offset(@col, @tag, (@i + 1));
}
// Make grid
//
.make-grid(@breakpoint, @cols, @pref) {
  & when( @breakpoint > 0 ){
    @media(min-width: @breakpoint) {
      .generate-columns(@cols, @pref);
      .generate-offset(@cols, @pref);
    }
  }
  & when( @breakpoint = 0 ){
    .generate-columns(@cols, @pref);
    .generate-offset(@cols, @pref);
  }
}
// Run make-grid for every breakpoint
//
.loop(@index) when (@index > 0){
    // run loop first to change order
    .loop ((@index - 1));

    .make-grid(
      extract(@breakpoints, @index),
      extract(@columns, @index),
      extract(@prefixes, @index)
    );
}
.loop(length(@breakpoints));

你的问题是因为e()(或~())函数的输出总是一个字符串,你不能用它来执行数学运算操作或比较等。您可以通过在 @media 查询中添加以下行(并注释掉混合调用)来验证这一点。

columnIsNumber: isnumber(@column); 
/* with your current method this will always return false */

要解决这个问题,您应该避免对要对其执行数学运算的任何变量使用 e() 函数。例如,您可以将您的 mixin 更改为如下所示(请参阅内联注释以了解所做的更改):

@prefixes: 'sm', 'md', 'lg';
@breakpoints: '0', '100rem', '140rem';
@columns: 2, 6, 12; /* note the exclusion of quotes */

.generate-offset(@n, @tag, @i: 1) when (@i < @n) {
  .offset--@{tag}-@{i} {
    margin-left: (@i * 100% / @n);
  }
  .generate-offset(@n, @tag, (@i + 1));
}

// Grid loops

.loop(@index, @count) when (@index > 0){
    // extract variables
    @current: (@count - @index);
    @breakpoint: e(extract(@breakpoints, @current));
    @column: extract(@columns, @current); /* avoid using e() */
    @prefix: e(extract(@prefixes, @current));
    @media (min-width: @breakpoint) {
        .generate-columns(@column, @prefix);
        /*columnIsNumber: isnumber(@column);*/
        .generate-offset(@column, @prefix);
    }

    .loop ((@index - 1), @count);
}

// run
@grids: length(@breakpoints);
.loop(@grids, (@grids + 1));

当然,您可以使用自己的代码(在变量声明中使用引号,在 mixin 中使用 e())并使用一些 JS 评估来完成此操作。但我不推荐这种方法,因为在我看来它只会增加复杂性。

@media (min-width: @breakpoint) {
    .generate-columns(@column, @prefix);
    @col: `function(){return @{column}}()`; /* JS evaluation */
    /*columnIsNumber: isnumber(@col);*/
    .generate-offset(@col, @prefix);
}

@media (min-width: @breakpoint) {
    .generate-columns(@column, @prefix);
    @col: `function(){return parseInt(@{column},10)}()`; /* JS evaluation */
    /*columnIsNumber: isnumber(@col);*/
    .generate-offset(@col, @prefix);
}