简体   繁体   English

如何在LESS中将多个类名传递给mixin

[英]How to pass multiple class names to a mixin in LESS

I'm making a view that displays transactions on an account, and I want to colour-code the transaction type/state. 我正在创建一个显示帐户交易的视图,并且要对交易类型/状态进行颜色编码。 I also want to show a legend explaining the colour codes. 我还想显示一个说明颜色代码的图例。

I want an end result that's structured like this: 我想要这样的最终结果:

HTML HTML

<table id="transactions">
  <thead>
    <tr>
      <th colspan="2">
        Transactions
      </th>
    </tr>
  </thead>
  <tbody>
    <tr class="credit">
      <td>A credit</td>
      <td>$1.00</td>
    </tr>
    <tr class="debit paid">
      <td>A paid debit</td>
      <td>($2.00)</td>
    </tr>
    <tr class="debit unpaid">
      <td>An unpaid debit</td>
      <td>($3.00)</td>
    </tr>
  </tbody>
</table>
<hr/>
<table id="legend">
  <thead>
    <tr>
      <th colspan="3">
        Legend
      </th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td class="credit">Credit</td>
      <td class="debit paid">Paid</td>
      <td class="debit unpaid">Unpaid</td>
    </tr>
  </tbody>
</table>

CSS CSS

table#transactions > tbody > tr.credit {
  color: limegreen;
}

table#legend > tbody > tr > td.credit {
  color: limegreen;
}

table#transactions > tbody > tr.debit.paid {
  color: goldenrod;
}

table#legend > tbody > tr > td.debit.paid {
  color: goldenrod;
}

table#transactions > tbody > tr.debit.unpaid {
  color: crimson;
}

table#legend > tbody > tr > td.debit.unpaid {
  color: crimson;
}

(CodePen) (CodePen)

Note that the "debits" use two class names, to tell them apart from the credits. 请注意,“借方”使用两个类名,以区别于贷方。

Clearly there's a bit of redundancy there, which I tried to refactor into this (invalid) LESS code: 显然那里有一些冗余,我试图将其重构为这个(无效的)LESS代码:

.transaction-status(@class, @color) {
  table#transactions > tbody > tr@{class} {
    color: @color;
  }

  table#legend > tbody > tr > td@{class} {
    color: @color;
  }  
}

.transaction-status(.credit, limegreen);
.transaction-status(.debit.paid, goldenrod);
.transaction-status(.debit.unpaid, crimson);

A possible workaround would be to rejigger things so the different transaction types have a single unique class name but that feels like time travelling to the time of IE6. 一个可能的解决方法是重新调整事情,以便不同的事务类型具有单个唯一的类名,但是感觉就像时间在移动到IE6一样。 Ie I'm aware of, but would like to avoid this valid LESS, which seems so close, and yet so far: 即我知道,但想避免这种有效的LESS,它看起来如此之近,但到目前为止:

.transaction-status(@class, @color) {
  table#transactions > tbody > tr.@{class} {
    color: @color;
  }

  table#legend > tbody > tr > td.@{class} {
    color: @color;
  }  
}

.transaction-status(credit, limegreen);
.transaction-status(debit-paid, goldenrod);
.transaction-status(debit-unpaid, crimson);

I tried quoting the class names, but even though that makes the first LESS sample compile, the quotes are passed to the output CSS. 我尝试用引号引用类名,但是即使可以编译第一个LESS示例,引号也会传递到输出CSS。 So, is there a way to pass something else than an "identifier" as a parameter to a LESS mixin, and have it work in selector interpolation correctly? 因此,是否有一种方法可以将除“标识符”以外的其他内容作为参数传递给LESS mixin,并使其在选择器插值中正常工作?

Option 1: 选项1:

As you mentioned, one option is to pass the value within quotes. 如您所述,一种选择是在引号内传递值。 But when that is done, you need to make sure to remove them before using them to perform selector interpolation. 但是,这样做之后,您需要确保在使用它们执行选择器插值之前将其删除。 This can be done by either using the ~() or the e() built-in functions. 这可以通过使用~()e()内置函数来完成。 Both of them will strip out the quotes from the input value. 它们都将从输入值中删除引号。 Once this is done, the temporary variable whose value doesnt have the quotes can be used for selector interpolation like below: 一旦完成,其值不带引号的临时变量可用于选择器插值,如下所示:

.transaction-status(@class, @color) {
    @className: ~"@{class}";
    table#transactions > tbody > tr@{className} {
        color: @color;
    }

    table#legend > tbody > tr > td@{className} {
        color: @color;
    }  
}

.transaction-status(".credit", limegreen);
.transaction-status(".debit.paid", goldenrod);
.transaction-status(".debit.unpaid", crimson);

Option 2: (a bit round about in my opinion) 选项2 :(我认为有点过头)

You can also use the ... option to pass in as many classes as required (note that this needs a small change to the order in which the inputs are passed) and then convert it to a string and use the replace function to add the . 您还可以使用...选项根据需要传入尽可能多的类(请注意,这需要对传递输入的顺序进行少量更改),然后将其转换为字符串,并使用replace函数添加. . The replace function is required because the converted string would be of the format class1 class2 (space separator). 需要replace函数,因为转换后的字符串的格式将为class1 class2 (空格分隔符)。

.transaction-status(@color, @class...) {
    @className: e(replace("@{class}" , " " , ".", 'g' )); 
    /* arguments: input string, pattern to match, replacement value, regex flags */
    table#transactions > tbody > tr.@{className} {
        color: @color;
    }

    table#legend > tbody > tr > td.@{className} {
        color: @color;
    }   
}

.transaction-status(limegreen, credit);
.transaction-status(goldenrod, debit, paid);
.transaction-status(crimson, debit, unpaid);

Note: Option 2 would work only with Less v.1.7.0 and above because the replace function was introduced only in v1.7.0. 注意:选项2仅适用于Less v.1.7.0及更高版本,因为replace功能仅在v1.7.0中引入。

It looks like you could color the whole row in either case? 看起来无论哪种情况,您都可以为整行着色? If so, a simple nesting of your selectors would reduce duplication, and arguably be easier to read: 如果是这样,选择器的简单嵌套将减少重复,并且可以说更易于阅读:

table#transactions, table#legend {
    & > tbody > tr {
      &.credit {
        color: limegreen;
      }

      &.debit.paid {
        color: goldenrod;
      }

      &.debit.unpaid {
        color: crimson;
      }
    }
  }
}

But that doesn't let you easily reuse these class/color combinations in other parts of your code, which is something that you very well may want to do. 但这不能让您轻松地在代码的其他部分中重用这些类/颜色组合,这是您很想做的。 I would define your color classes more like this: 我将更像这样定义您的颜色类别:

.trans-status {
  &.credit {
    color: limegreen;
  }

  &.debit.paid {
    color: goldenrod;
  }

  &.debit.unpaid {
    color: crimson;
  }
}

And then you can apply the appropriate classes with more precision: 然后,您可以更精确地应用适当的类:

<tr>
  <td>An unpaid debit</td>
  <td class="trans-status debit unpaid">($3.00)</td>
</tr>

Here's a fork of your example using this approach: 这是使用此方法的示例的分支:

https://codepen.io/anon/pen/mxMLPG https://codepen.io/anon/pen/mxMLPG

Another advantage to using this approach, is that you can also apply these styles as mixins in your Less files. 使用此方法的另一个优点是,您还可以在Less文件中将这些样式作为mixins应用。 For example, if you needed to use the same color values in other parts of your code, you could define the colors more abstractly, and apply them in different ways: 例如,如果您需要在代码的其他部分中使用相同的颜色值,则可以更抽象地定义颜色,并以不同的方式应用它们:

.status {
  .success {
    color: limegreen;
  }

  .confirmed {
    color: goldenrod;
  }

  .warning {
    color: crimson;
  }
}

.negative-balance {
  .status.warning;
}

#rewards-points {
  .status.success;
}

It's also worth noting that in cases where you do need to pass rules/mixins into other mixins, Less 1.7.0 and above supports Detatched Rulesets to accomplish this same sort of thing with a cleaner syntax than string interpolation. 还值得注意的是,在确实需要将规则/混合输入传递到其他混合输入的情况下,Less 1.7.0及更高版本支持分离规则集以比字符串插值更干净的语法来完成相同的任务。 The original question doesn't really warrant this level of complexity, but it can be useful for things like breakpoints: 最初的问题并不能保证如此复杂,但是对于断点之类的问题可能很有用:

.break(@min-width; @max-width; @rules) {
  @media only screen and (min-width:@min-width) 
    and (max-width: @max-width){
    @rules();
  }
}

.break(0px, 480px, {
  font-size: 10px;
  padding: 8px;
});

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM