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



我正在创建一个显示账户交易的视图,我想对交易类型/状态进行彩色编码。我还想展示一个图例来解释颜色代码。

我想要一个这样结构的最终结果:

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

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)

请注意,"借项"使用两个类名,将它们与贷项区分开来。

很明显,这里有一点冗余,我试图将其重构为这个(无效的)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);

一个可能的解决方法是重新调整事物,使不同的事务类型有一个唯一的类名,但这感觉就像是时间旅行到IE6时代。也就是说,我知道,但我想避免这个有效的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);

我试着引用类名,但即使这使得第一个LESS样本编译成功,引号也会传递给输出CSS。那么,有没有一种方法可以将"标识符"以外的其他东西作为参数传递给LESS mixin,并使其正确地在选择器插值中工作?

选项1:

正如您所提到的,一种选择是在引号中传递值。但当完成此操作时,您需要确保在使用它们执行选择器插值之前删除它们。这可以通过使用~()e()内置函数来实现。两者都将从输入值中去掉引号。一旦完成,其值没有引号的临时变量可以用于选择器插值,如下所示:

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

选项2:(在我看来有点圆)

您还可以使用...选项根据需要传入尽可能多的类(请注意,这需要对输入的传递顺序进行小的更改),然后将其转换为字符串,并使用replace函数添加.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);

注意:选项2仅适用于Less v.1.7.0及更高版本,因为replace功能仅在v1.7.0中引入。

看起来在任何一种情况下都可以为整行上色?如果是这样的话,一个简单的选择器嵌套将减少重复,并且可以说更容易阅读:

table#transactions, table#legend {
    & > tbody > tr {
      &.credit {
        color: limegreen;
      }
      &.debit.paid {
        color: goldenrod;
      }
      &.debit.unpaid {
        color: crimson;
      }
    }
  }
}

但这并不能让你在代码的其他部分轻松地重用这些类/颜色组合,这是你很可能想要做的事情

.trans-status {
  &.credit {
    color: limegreen;
  }
  &.debit.paid {
    color: goldenrod;
  }
  &.debit.unpaid {
    color: crimson;
  }
}

然后你可以更精确地应用适当的类:

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

下面是一个使用这种方法的例子:

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

使用这种方法的另一个优点是,您还可以在Less文件中将这些样式作为mixin应用。例如,如果你需要在代码的其他部分使用相同的颜色值,你可以更抽象地定义颜色,并以不同的方式应用它们:

.status {
  .success {
    color: limegreen;
  }
  .confirmed {
    color: goldenrod;
  }
  .warning {
    color: crimson;
  }
}
.negative-balance {
  .status.warning;
}
#rewards-points {
  .status.success;
}

同样值得注意的是,如果确实需要将规则/mixin传递到其他mixin中,Less 1.7.0及以上版本支持Detatched Ruleset,以比字符串插值更干净的语法来完成同样的事情。最初的问题并不能真正保证这种复杂程度,但它对断点之类的东西很有用:

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

最新更新