【问题标题】:LESS: How can I pass a mixin as an argument to another mixin?LESS:如何将一个 mixin 作为参数传递给另一个 mixin?
【发布时间】:2017-01-18 13:57:08
【问题描述】:

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

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

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

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

我正在尝试构建一个非常简单的基于 flex 的网格系统,我正在尝试将提到的 mixin 作为参数传递,这样我就可以拥有一个通用的 .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 '('

【问题讨论】:

    标签: css less less-mixins


    【解决方案1】:

    在这种特殊情况下(与具有任意 mixin 名称的一般情况不同)我会说你错过了这样一个事实,即在 .on-small/.on-medium 这些 small 和 medium 事情也不过如此参数,因此不应该是 mixin 名称的一部分。考虑到这一点,您的示例变为:

    .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);
    

    .grid-col-on-* mixin 也是如此,它们只是一个:

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

    等等。

    如果您真的想要一个灵活/通用的网格 - 永远不要将设备/断点名称硬编码到 mixin 或变量名称中(更多原理和示例请参阅 https://github.com/less/less.js/issues/2702)。

    【讨论】:

    • 这真的很有帮助!谢谢!
    【解决方案2】:

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

    相反,您可以执行类似下面的操作,直接从包装器 mixin 中调用媒体查询 mixin,而不是 .make-col mixin。由于 wrapper 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);
      });  
    }
    

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

    @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);
    }
    

    【讨论】:

      猜你喜欢
      • 2012-07-18
      • 2013-06-03
      • 2015-05-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-01-30
      • 2014-08-27
      • 1970-01-01
      相关资源
      最近更新 更多