LESS:我如何将mixin作为参数传递给另一个mixin?

时间:2017-01-18 13:57:09

标签: css less less-mixins

我有一些基本的mixin使用媒体查询应用一些规则

.on-small(@rules) {
  @media (@minWidthSmall) { @rules(); }
}

.on-medium(@rules) {
  @media (@minWidthMedium) { @rules(); }
}

// and .on-large, .on-x-large and so on

我正在尝试构建一个非常简单的基于flex的网格系统,我试图将提到的mixins作为参数传递,因此我可以使用通用的.make-column mixin。如下:

.make-col(@break-point-mixin, @span, @size) {
  flex: 1;
  box-sizing: border-box;


  /***********************************************************
  Is the following line possible in LESS somehow?
  ***********************************************************/
  @break-point-mixin({
    width: percentage(@span/@size);
    min-width: percentage(@span/@size);
  });
}

.grid-col-on-small(@span: 1, @size: 1) {
  .make-col(@break-point-mixin: .on-small, @span, @size);
}

.grid-col-on-medium(@span: 1, @size: 1) {
  .make-col(@break-point-mixin: .on-medium, @span, @size);
}

但不幸的是,将@break-point-mixin作为参数传递并从.make-col内部调用它会崩溃:

Unrecognised input. Possibly missing opening '('

2 个答案:

答案 0 :(得分:4)

不,你不能将mixin名称作为参数发送并以这种方式使用它。

相反,您可以执行类似下面的操作,直接从包装器mixin而不是.make-col mixin中调用媒体查询mixin。由于包装器mixin知道媒体查询mixin需要的变量,这不会导致任何问题。

.grid-col-on-small(@span: 1, @size: 1) {
  .make-col(@span, @size);
  .on-small({
    width: percentage(@span / @size);
    min-width: percentage(@span / @size);
  });
}

.grid-col-on-medium(@span: 1, @size: 1) {
  .make-col(@span, @size);
  .on-medium({
    width: percentage(@span / @size);
    min-width: percentage(@span / @size);
  });  
}

如果您担心重写上述mixins中的规则,那么您可以将它们设置为如下所示的规则集并使用它。

@colRules: {
             width: percentage(@span / @size);
             min-width: percentage(@span / @size);
           };

.grid-col-on-small(@span: 1, @size: 1) {
  .make-col(@span, @size);
  .on-small(@colRules);
}

.grid-col-on-medium(@span: 1, @size: 1) {
  .make-col(@span, @size);
  .on-medium(@colRules);  
}

或者,您可以将mixin名称作为参数发送,并使用如下所示的警卫。由于我们在这里处理断点并且不应该有很多断点,这种方法应该有所帮助,并且可能会得到我的投票。

@colRules: {
             width: percentage(@span / @size);
             min-width: percentage(@span / @size);
           };

.make-col(@breakpoint, @span, @size) {
  flex: 1;
  box-sizing: border-box;
  & when (@breakpoint = s) {
    .on-small(@colRules); /* or you could replace this with that mixin's content also */
  }
  & when (@breakpoint = m) {
    .on-medium(@colRules);
  }
  /* and so on for the rest */
}

.grid-col-on-small(@span: 1, @size: 1) {
  .make-col(s, @span, @size);
}

.grid-col-on-medium(@span: 1, @size: 1) {
  .make-col(m, @span, @size);
}

答案 1 :(得分:3)

在这种特殊情况下(与任意mixin名称的一般情况不同)我说你错过.on-small / .on-medium small medium这一事实和.on(small, @rules) { @media (@minWidthSmall) {@rules();} } .on(medium, @rules) { @media (@minWidthMedium) {@rules();} } .make-col(@device, @span, @size) { flex: 1; box-sizing: border-box; .on(@device, { width: percentage(@span/@size); min-width: percentage(@span/@size); }); } // usage: .make-col(small, @span, @size); 事物也只是参数,因此不应该是mixin名称的一部分。考虑到这一点,你的例子就变成了:

.grid-col-on-*

对于你的.grid-col-on(@device, @span: 1, @size: 1) { .make-col(@device, @span, @size); } mixins来说,它们只是一个:

A = {'a':1, 'b':2, 'c':3}
B = {'b':3, 'c':4, 'd':5}
Merged = dict(A, **B)
Merged == {'a':1, 'b':3, 'c':3, 'd':5}

等等。

如果你真的想要灵活/通用网格 - 从不将设备/断点名称硬编码为mixin或变量名称(有关更多基本原理和示例,请参阅https://github.com/less/less.js/issues/2702)。