Less.js: :扩展混合

创建于 2013-02-12  ·  112评论  ·  资料来源: less/less.js

提出此功能请求作为此问题的解决方案https://github.com/cloudhead/less.js/issues/1155

这是概要

mixin 的绝妙之处在于它们可以加快开发速度,保持我的工作台面干净,我只需编写一次它们,并且我知道编译后的结果是什么。 然而,mixin 的一个缺点是它们不是 DRY。 尤其是当您大量使用“实用程序”mixin 时,例如 clearfix。 这就是 extends _可能_ 是一个更好的选择的地方。 事实上,这是一个很好的扩展 mixins 的具体用例。 它基本上就像扩展嵌套选择器一样工作,接受混合。 所以 mixins 根本不会改变,它们仍然会以相同的方式工作。 如果你有一个 mixin 并且不使用它,它不会显示在编译的 CSS 中。 如果您确实使用它,它的属性仍将显示在使用它的每个选择器的编译代码中。 如果你_扩展_一个mixin,

.clearfix() {
    // stuff
}
.navbar {
    &:extend(.clearfix());
}
.banner {
    &:extend(.clearfix());
}

编译结果将是:

.navbar,
.banner {
   // clearfix stuff
}

所以 mixin 属性仍然由扩展它的选择器继承,但 mixin(选择器)本身不会出现在编译结果中。

这将使扩展和混合比单独使用更强大。

feature request medium priority up-for-grabs

最有用的评论

公共服务声明

在任何时候,你都可以提交一个拉取请求,或者与开发人员合作来获取一个,并且这个特性很可能被合并。Less.js 库需要更多来自像这个线程中的人这样的个人的定期贡献. 这不是任何人的责任。 这完全取决于一个人看到这个线程,或者需要这个功能,并花时间实现它。

如果您的回答是您不是开发人员,那么您可以通过许多其他方式以非开发角色支持该项目,无论是为新功能提供所需的文档,还是在网站上设计支持、运行测试、提供反馈关于问题,项目管理,在 Stack Overflow 上回答问题,撰写博客文章,发布关于 Less 的推文,为 CSS 和网络社区做出贡献,以及编写 Less 库。

其中许多任务是由开发人员完成的,因此他们可以为开发做出贡献的时间都花在了这些其他任务上。

如果您_是_一名开发人员,而您的回答是“我没有时间”,那么这就是此问题悬而未决的确切原因。 功能是否完成由您 100% 决定,所以询问为什么“某人”没有完成它是没有用的。 _你就是那个人。_它会发生,我_保证_它会发生,如果你参与这个项目。 您可以参与网络上最流行的开源工具之一。 你可以改变......成千上万的生活? 数十万? 百万? 作为附带的好处,您可以确保您最喜欢的功能早日出现。

如果您希望此或任何功能发生,请使其发生。 我们很想拥有你。 我们很乐意与您合作! 随着社区的发展,越少越好,越少越好!

而且,听着,我很欣赏有时人们真的完全没有时间做出贡献,但仍然真的希望某个特定功能发生。 没关系。 我只想说,如果你处于那种情况,你的目标是对人们付出时间(有时是金钱)来帮助你的同情和感激,我相信 Less 社区的其他人会尽最大努力继续这样做,因为他们有能力。

真挚地,
Matthew Dean,Less.js 核心团队成员

所有112条评论

我喜欢它,但要清楚..这不允许你做你以前不能做的事情,它只是意味着你得到..

.navbar,
.banner {
    // clearfix stuff
}

而不是

.navbar {
    // clearfix stuff
}
.banner {
    // clearfix stuff
}

还是我误解了?

我希望同时拥有参数化和通常的 mixin

.navbar,
.banner {
    // clearfix stuff
}
.....

或者

.clearfix,
.navbar,
.banner {
    // clearfix stuff
}
....

每当您需要时,我知道这是 mixin 已经工作的模拟方式,所以问题主要是具有灵活性和更好地处理最终 CSS 输出的优化方式。

一定

.clearfix,
.navbar,
.banner {
    // clearfix stuff
}

短于

 .clearfix {
    // clearfix stuff
  }
 .navbar{
    // clearfix stuff
 }
.banner {
    // clearfix stuff
}

对于更复杂的可能很重要的例子,我知道有些人只是因为这种短缺而转向了 SASS

常规的 mixins 无法改变。 它们几乎是 Less 的固定装置。 @agatronic ,是的,我也是这么看的。 但这也存在挑战,比如我们是否能够扩展参数化混合? 如果是这样,那将如何运作? 假设这是支持的,假设您扩展了一个参数混合两次,但每次使用不同的变量,如下所示:

.transition(@transition) {
  -webkit-transition: @transition;
     -moz-transition: @transition;
       -o-transition: @transition;
          transition: @transition;
}
.navbar {
    &:extend(.transition(opacity .2s linear));
}
.banner {
    &:extend(.transition(opacity .3s linear));
}

我想它可能会创建 mixin 的两个副本,这不是更少的代码,并且与常规 mixin 相比没有优势:

.navbar {
  -webkit-transition: opacity .2s linear;
     -moz-transition: opacity .2s linear;
       -o-transition: opacity .2s linear;
          transition: opacity .2s linear;
}
.banner {
  -webkit-transition: opacity .3s linear;
     -moz-transition: opacity .3s linear;
       -o-transition: opacity .3s linear;
          transition: opacity .3s linear;
}

然而,你可能会经常使用这个特定的 mixin,所以当你在.dropdown上再次使用 mixin 时,它的变量与.banner ,它可能会导致:

.navbar {
  -webkit-transition: opacity .2s linear;
     -moz-transition: opacity .2s linear;
       -o-transition: opacity .2s linear;
          transition: opacity .2s linear;
}
.banner,
.dropdown {
  -webkit-transition: opacity .3s linear;
     -moz-transition: opacity .3s linear;
       -o-transition: opacity .3s linear;
          transition: opacity .3s linear;
}

这就是让我感兴趣的原因。 听到别人的反馈也会很好

@jonschlinkert是的,这是更好的说明,谢谢。 正如我所说的那样双手! 但理解虽然它增加了另一个层次的同谋,并且需要做/不做深思熟虑

使用此模式可以很容易地实现您引用的方法中的扩展:

.transition(@transition) {
    -webkit-transition: @transition;
     -moz-transition: @transition;
       -o-transition: @transition;
          transition: @transition;
}

.quickOpacity1(){
    .transition(opacity .2s linear);
}

.quickOpacity2(){
    .transition(opacity .3s linear);
}

.navbar{
    .quickOpacity1();
}

.banner,
.dropdown{
    .quickOpacity2();
}

以上是将半扩展混合注入到 2 个新声明中。

对于 clearfix 也很容易使用下面的类似模式,它不仅将 clearfix 创建为一个类,而且将这些 clearfix 样式注入到新声明中。

.clearfix{
  //clearfix stuff
}
.navbar,
.banner {
    .clearfix;
}

@krismeister我认为这可能会引起混淆。 您描述的模式实际上只是嵌套的 mixin,或 mixin 继承模式。 以相反的方式扩展工作。

@jonschlinkert Mixin 继承 - 一个伟大的名字。 似乎上面的两个示例都试图从父级继承输出 - 这是扩展的核心功能。 您可能同意我的示例的输出是您的预期输出。

但是,我从重读您的原始评论中了解到 - 您希望将输出加入一个 CSS 规则。 虽然它最初写成2。

实际上:extend非常棒。 我要完全书呆子了,但这一切都归结为“什么被移动到了哪里”。 将 mixin 想象为“将 mixin 的属性传递给使用它的选择器”。 并认为:extend是相反的,“将使用它的选择器传递给 mixin 本身。” 不是 _selector 的属性,只是选择器本身。 所以如果你这样做:

.some-mixin() {
    padding-top: 100px;
    background: #f7f7f7;
}


// a selector that is extending the mixin
.alert:extend( .some-mixin() ) {
    border: 1px solid #e5e5e5;
}
// another selector extending the mixin
section:extend(.some-mixin()) {
    margin: 20px 0;
}

这将导致:

// The selectors that extended the mixin are now where the mixin used to be.
.alert,
section {
    padding-top: 100px;
    background: #f7f7f7;
}

// And the properties of the mixin did not get copied down below
// so we saved a line or two of code.
.alert {
    border: 1px solid #e5e5e5;
}
section {
    margin: 20px 0;
}

希望这更有意义。 我很乐意随时提供帮助。

@agatronic@matthewdl@DesignByOnyx ,只是一个想法,我知道这是一种不寻常的方法,但假设对此没有技术挑战,并且假设我们允许使用逗号分隔的选择器列表,也许扩展 _should_ 感觉更像是一个数组. 您如何看待将语法更改为: :extend[N]

我认为当 mixin 被扩展时,它对眼睛也更容易:

section:extend[.some-mixin(), .another-mixin()] {
    margin: 20px 0;
}

无论哪种方式我都很好,但对方括号的感觉是正确的。

@jonschlinkert - []表示 css 中的属性,而不是数组,因为:extend()被选择是因为它链接到伪选择器,所以我强烈认为应该保留正常的括号。

好点,我同意。

我同意括号看起来和读起来很好,但是我们必须坚持我们已经选择的语法。

赞一下extend(N) 语法,感觉更像自然CSS,原因与@agatronic 相同

扩展 mixins 不是一个坏主意。 不确定示例语法,@jonschlinkert。 不是我不喜欢它; 我只是真的不明白你写的什么。

我认为您的意思是您想要定义“引入”相​​同 mixin 内容的类,但实际上并不在生成的 CSS 中重复。 我不会称之为扩展混合。 也就是说,您不是在更改 mixin 定义(与扩展定义对选择器所做的方式相同),您实际上是在更改(扩展)结果类。

所以,如果我错了,请纠正我,但您的导航栏/横幅/下拉示例不会得到以下支持:

.navbar {
  .transition(opacity .2s linear);
}
.banner {
  .transition(opacity .3s linear);
}
.dropdown:extend(.banner) { }

也就是说,像往常一样扩展类? 我只是想了解一下您的使用模式,并且将扩展用于 mixin 似乎与其用于扩展选择器的使用和命名不一致。 您能否提供更多详细信息,说明为什么需要/想要在扩展调用中引用 mixin,而不是扩展引用 mixin 的选择器?

这就是我得到它的方式

所需的最终 CSS 输出

.sometingShared,
.anotherClass,
.anotherYetClass,
.yetClass {
    // amount of shared code here
}

.anotherClass,
.anotherYetClass {
    // did something dynamic with a
}

.yetClass {
    // did something dynamic with b
}

.anotherClass {
    // native another class code
}

.anotherYetClass {
    // native another yet class code
}

.yetClass {
    // native yet class code
}

您必须使用当前版本的 LESS 来获得所需的输出

.somethingShared,
.anotherClass,
.anotherYetClass,
.yetClass {
    // amount of shared code here
}

.someMixin(@val) {
    // do something dynamic with val
}

.anotherClass,
.anotherYetClass {
    .someMixin(a);
}

.yetClass {
    .someMixin(b);
}

.anotherClass {
    // native another class code
}

.anotherYetClass {
    // native another yet class code
}

.yetClass {
    // native yet class code
}

建议较少的语法

.somethingShared {
    // amount of shared code here
}

.someMixin(@val) {
    // do something dynamic with val
}

.anotherClass:extend(.sometingShared, .someMixin(a)) {
    // native another class code
}

.anotherYetClass:extend(.sometingShared, .someMixin(a)) {
    // native another yet class code
}

.yetClass:extend(.sometingShared, .someMixin(b)) {
    // native yet class code
}

虽然扩展仅在您拥有大量共享代码时才有用,但在其他情况下,普通的 mixin 使用更受青睐。

只是有点,现场虚拟样本,旨在只是玩耍

http://jsbin.com/opekon/1/edit
http://jsbin.com/opekon/2/edit
http://jsbin.com/opekon/3/edit
http://jsbin.com/opekon/4/edit

如前所述,对于像我这样懒惰的人来说,在某些情况下可能会真正提高性能:) 优化 LESS 代码只是因为它影响了进一步的灵活性

这是一篇关于扩展的很好的博客文章,涵盖了关于 SASS 如何处理扩展的几件事,我们从其他人的做法中学习可能是明智的。 http://designshack.net/articles/css/semantic-grid-class-naming-with-placeholder-selectors-in-sass-3-2/

特别是,我相信我关于扩展 mixin 的提议基本上会达到与 SASS“占位符”相同的最终结果,但不必创建无用的、多余的占位符类。

编辑:是的,这是另一篇很好地总结了占位符的帖子。 这正是我提议的扩展 mixins http://maximilianhoffmann.com/article/placeholder-selectors

我个人更喜欢这一点,而不是所有其他与扩展相关的功能。 毫无疑问。 这是一个强有力的声明,但如果其他人不同意,我认为我没有很好地解释它。 这是相当强大的东西。

我觉得SASS

 %tile {
  width: 200px;
  height: 200px;
  margin-right: 20px;
}

等于参数混合,专为扩展而设计,在关注点分离方面可能不是那么糟糕。 但是是的,这就是 CSS,难道它不是应该尽可能简单吗?

@agatronic在我们谈论时,这个扩展https://github.com/agatronic/less.js/blob/master/lib/less/tree/extend.js应该是什么? 注意到它已经在主要的较少分支中。 对不起,菜鸟问题。

@dmi3y它是从准备 1.4.0 的拉取请求中提取的第一个扩展版本 - 它代表扩展节点

谢谢@agatronic ,现在我知道我错过了多少;)

@dmi3y请随时继续添加到对话中,让我们尝试将这个问题保持在更高的水平,以便我们得出结论。 也可以随时给我发电子邮件,我很高兴与您讨论 mixins 和扩展如何工作(我的联系信息在我的个人资料中)。 还有一个快速评论,以避免对该线程的进一步混淆。 你的例子:

%tile {
    width: 200px;
    height: 200px;
    margin-right: 20px;
}

这是 SCSS“占位符”的语法,它在 SCSS 规范中实现,以完成类似于我提议的扩展 mixin 的内容。 但这与参数化无关。 参数混合只是简单的 _mixins 接受参数_,这意味着它们的值可以在每次使用时改变。

@matthewdl

我认为你的意思是你想定义“拉入”相同混合内容的类,但实际上并不在结果 CSS 中重复

你的导航栏/横幅/下拉示例不支持...

不,操作点被遗漏了,恰恰相反。 也许混淆是因为我在我的例子中犯了专注于参数混合的错误。

所以首先,我认为重要的是要说明并非所有的 mixin 都是参数化的,许多是为了_不_接受参数而创建的。 一些mixin,比如clearfix,在使用时会反复使用而不会改变任何变量。 这些是一个完美的用例,说明了为什么扩展 mixin 是有利的。

参数化与否,在它们所有的荣耀 mixin 中都有一个缺点,即每次使用它时,它的属性都会重复。 因此,让我尝试解释如何仅使用“常规 mixins”来扩展 mixin,并继续您上面使用的示例。

鉴于您的示例,需要提出两个完全独立且不相关的要点:

  1. 无论是否扩展,横幅类仍然会显示在编译的 CSS 中,但如果横幅类是混合,它只会在使用(扩展或混合)时出现在结果 CSS 中。 仅这一点就很有价值。 和
  2. 当你 _extend 一个 mixin_ 时,我们不会一遍又一遍地复制相同的属性,而是将实际的选择器本身复制到 mixin 的位置。

但这只是一个例子。 考虑到 Twitter Bootstrap 中的某一点, .clearfix() mixin 单独在其他选择器中使用了 20 多次,并且它还嵌套在 4 或 5 个其他结构性 mixin 中,例如.container-fixed().make-row()#grid > .core() 。 这意味着这些 mixin _也_每次使用它们时

这更有意义吗? 因此,为了避免将 clearfix mixin 的属性复制 20 次以上,我们会将使用 clearfix mixin 的选择器分组到 mixin 本身的位置,并且这些属性只会被声明一次。 再说一次,这只是一个 mixin,想象一下扩展常规 mixin 丢失的净收益,而不是复制它们的属性。 正如我在上面某处提到的,为了特殊性和覆盖,有时仍需要使用常规 mixin 而无需扩展,但这并不会降低扩展那些不扩展的价值。 事实上,我会亲自创建额外的 mixin 来专门用于扩展,否则我不会使用它。

我上面的第二个例子关注的是扩展如何与参数化混合一起工作,所以希望这完成了图片并且现在更有意义? 如果没有,我上面链接的文章应该可以消除任何混淆。 扩展 mixins 非常强大和有用,并且可以让您获得与扩展嵌套选择器相同的最终结果,但专门使用 mixins 而不是任何嵌套选择器。 这允许您以最有可能提供所需结果的方式组织选择器,并避免意外后果。 @DesignByOnyx@agatronic@matthewdl ,这里有什么我遗漏或忘记的吗? 我们可以做些什么来消除混乱?

谢谢。 我想我了解用例,我认为这句话说得最好:

横幅类是一个 mixin,如果使用(扩展或混合),它只会出现在结果 CSS 中

这对我来说很有意义。 可能我要挂断的是整体:extend语法还不是最终的。 但是,你提出了有说服力的案例。

我想说的是,一旦我们最终确定了选择器块,如果扩展 mixin 的行为最终与扩展选择器的行为相匹配(关键区别在于您刚才所说的那一行,即没有选择器在 CSS 中输出用于扩展除非有初始用法),那么这对我来说很直观。

也就是说,如果我也可以这样做(或等效语法):

.facebook-button:extend( .button() all ) {
    border: 1px solid #e5e5e5;
}

......然后向我竖起大拇指。 但是,对我来说,所有这些都取决于我们为选择器解析:extend内容/方式/是否。 但是,撇开语法不谈,作为一个特性的想法,你是对的,它是合理的。

@jonschlinkert谢谢你,非常感谢你的认可,我一定会尽我所能,尽可能清楚地表达我的想法。 我认为听到未来发展的进展非常令人兴奋,是的,被听到。 你们所有人,用它做很棒的工作。

是的,这个例子,我必须在我之前的帖子中明确说明。

%tile {
   width: 200px;
   height: 200px;
   margin-right: 20px;
 }

取自 Jon 提供的 SASS 教程,它的主要目标是避免从不会使用的类中破坏 CSS 中的输出。 所以在这个特定的角度,它可以被看作是 LESS 中的空参数混合。 当您想使用它但不想将其输出到最终样式表时。

我正在参与这个讨论,并想为自己澄清以下评论:

如果横幅类是一个 mixin,它只会出现在结果 CSS 中,如果被使用(扩展或混合)

因此,使用更通用的 clearfix 示例,这是 LESS 和结果 CSS 吗?:

.clearfix() {
    &:before,
    &:after { content: " "; display: table; }

    &:after { clear: both; }
}
.something:extend( .clearfix() ) { }

/*
.clearfix:before,
.clearfix:after,
.something:before,
.something:after {
    content: " ";
    display: table;
}
.clearfix:after,
.something:after {
    clear: both;
}
*/

我最初希望.clearfix类在编译的 CSS 中保持省略。 就个人而言,我不会_需要_编译 CSS 中的类,因为我不会在标记中使用它,而且它是我的 CSS 中的额外字节。 无论哪种方式,我都没有强烈的意见,但对这一点的澄清将有助于我做出更好的评论。 谢谢。

这是...产生的 CSS 吗?:

我很高兴你问,但,只有.something类会出现在结果 CSS 中。 所以你在你最初的期望中是正确的。

只需阅读占位符链接,是的,我认为扩展 mixins 是一种更好、更少的方式来做事并获得相同的功能。

为了证实你的上述观点

.clearfix() {
    &:before,
    &:after { content: " "; display: table; }
    &:after { clear: both; }
}
.something:extend( .clearfix() ) { }

/*
.something:before,
.something:after {
    content: " ";
    display: table;
}
.something:after {
    clear: both;
}
*/

并且大概如果.clearfix() {定义是.clearfix {那么在扩展定义中使用或不使用括号调用它对输出没有任何影响..

使用伪类语法扩展特性是完全错误的,
因为“extend sth”不等于“match sth”,它对选择器应该的DOM结构没有任何意义。

你们这些人“发明”了很多坏主意。 最著名的一个是“重用”.xxx(类选择器)作为混合符号。至少它简化了从普通 CSS 到预处理器的迁移。但是 :extend 语法是我听过的最糟糕的主意。

我不想对我们的问题发表这种咆哮,但这不是我第一次听到这些事情,所以让我们谈谈 CSS 并清除空气。

你们这些人“发明”了很多坏主意。 最著名的一个是“重用”.xxx(类选择器)作为混合符号。.... :extend 语法是我听过的最糟糕的主意。

.xxx被称为隐式混入。 它有效,而且很容易理解。 事实上,这种语法在 CSS 规范中并不像使用 at 规则来设置实际样式那样“侵入性”。 @keyframes最接近于将被描述为样式的内容,并且_可能_被认为是我所说的一个例外,因为使用的标识符与 CSS 语法中的标识符产生式相匹配。 除了关键帧之外,一般来说 CSS at 规则主要用于基于“外部”信息的更高级别的配置和样式或样式表操作,这意味着样式本身之外,如字符编码( @charset ),或响应特定于设备的条件 ( @media )。

此外,我还能想到更糟糕的想法。 就像使用 at-rules 进行样式设置是其中之一,对同一功能使用两个 at-rules 是另一个。 当然,这完全取决于您的目标,如果您想以编程方式操作样式而不亲自接触它们,那么使用更钝和明显的语法结构可能有优势,这些语法结构可能更容易被解析器接收。 看起来您使用的是 Stylus,所以我很想听听您关于为什么其他语法具有优势的观点。

“extend sth”不等于“match sth”,它与选择器应该的DOM结构无关。

正确的。 带有nth _something_ 的伪类被 CSS 规范描述为“结构化”伪类。 但是,还有6 种其他类型的伪类:“动态”、“否定”、“目标”、“空白”、“UI 元素状态”和“语言”。 如果 CSS 规范确实描述了“扩展”功能,那么它可以非常优雅地作为“否定”和“目标”伪类之间的一个类别。

伪类允许基于文档树中的信息进行选择,但这可能不是扩展功能的最佳使用。

完全错误

一个比所有其他预处理器加起来还要大的社区不会错。 还有什么好说的?

@hax - 如果您像:extend线程上的其他人一样提出自己的解决方案,那么无意识的拖钓可能会变成有根据的讨论。 在非常有经验的前端开发人员和 L​​ESS 的重度用户之间经过数周的不同建议和审议后,我们找到了一个令人满意的解决方案,使用:extend语法。 如果您有更好的建议,请相信我 - 我们都在倾听。

要添加到@jonschlinkert.this:not(.that) { }.this:matches(.that) { }.this:extend(.that) { }在类别上是相似的。 即:“给定选择器 'this',以特定方式将其与选择器 'that' 联系起来。” 由于 LESS 经常扩展 CSS 中引入的概念和语法,因此它是该语言的一个非常合乎逻辑的扩展。 我们密切关注 CSS 规范,因此,反映了它的特质。 如果这个概念有些奇怪,它希望首先从 CSS 开始。 这就是为什么在我们的 mixin 守卫中,“AND”由单词“and”表示,而“OR”由逗号表示:因为这就是媒体查询中的方式。 我们的目标不是修复或更改 CSS,而是让 CSS 更易于使用,并使 CSS 作者完全熟悉 LESS。 :extend就是一个例子。 如果您知道如何使用:not ,您就知道如何使用:extend

如果我们为此使用更“隐式”的语法来避免嵌套括号并使扩展参数化混入更容易呢?

今天,我们使用这样的参数混合:

.square {
  .border-radius(9px);
}

而不是像这样扩展 mixin(因为你可能扩展一个普通类):

.square {
  &:extend(.border-radius);
}

我们可以这样扩展:

.box {
  .border-radius:extend(9px);
}
.square {
  .border-radius:extend(9px);
}
.rectangle {
  .border-radius:extend(4px);
}

区别在于“扩展混合”以分号结尾并在括号内声明一个或多个值, .border-radius:extend(9px); ,而不是列出要在括号内扩展的类并用花括号开始一个新的选择器块, .border-radius:extend(.some-class) {} 。 恕我直言,这不亚于隐式 mixins ( .border-radius; ),这是 LESS 最酷的功能之一,恕我直言。

在渲染输出中,任何“扩展参数混合”都将在原始混合的位置渲染,如下所示:

.box, 
.square {
    -webkit-border-radius: 9px;
    -moz-border-radius: 9px;
    border-radius: 9px;
}
.rectangle {
    -webkit-border-radius: 4px;
    -moz-border-radius: 4px;
    border-radius: 4px;
}
.some-other-class, 
.another-class, 
.and-another {
    -webkit-border-radius: 2px;
    -moz-border-radius: 2px;
    border-radius: 2px;
}

所以我个人喜欢这个,因为它足以背离选择器块内的“正常”扩展语法,使正在发生的事情变得足够明显,并且它与现有的 less 约定的微妙性相结合,无需过度解释什么你试图在代码中完成。 这个功能绝对是我个人愿望清单的顶部。

使用我在原始请求中给出的 clearfix 示例,这就是我修改后的语法的样子:

.clearfix() {
    // ...
}
.navbar {
    .clearfix:extend(); // instead of &:extend(.clearfix());
}
.banner {
    .clearfix:extend();
    &:extend(.some-class); // "implicit mixin" being extended
}

我喜欢你要去的地方。 我认为更友好的方法是在 _existing_ mixin 语法的末尾使用:extend ,如下所示:

.box {
  .border-radius(9px):extend;
}
.square {
  .border-radius(9px):extend;
}
.rectangle {
  .border-radius(4px):extend;
}

:extend之后省略括号会让你感觉它的用途与现有的扩展语法不同。

我可以采用任何方式,但我更喜欢.border-radius:extend(9px);因为它与扩展语法一致,IMO 很明显它是一个混合,但它也意味着参数/值正在被扩展 - 这将有助于解释为什么输出是“分组的”。

@jonschlinkert - 在这一点上,我非常重视您的意见,并将支持您认为最好的任何决定。 我会说你的方法感觉好像 9px 被传递给“扩展”而不是传递给 mixin 本身......但我对两者都很酷。

@DesignByOnyx感谢您的客气话。 你说的很有道理,我的“镜头”(在 Less 中)是这样的:

.this:extend(.that) {}

所以你的观点和我自己的观点是一致的。 @matthewdl@lukeapage你们中的任何一个对此有任何看法/意见吗? 我认为这两种语法都可以(也可能是其他语法),但不可否认,我并没有关注这两种语法的“面向未来”,因此两者都可能存在一些问题。 我只是很想看到这种情况发生,我认为扩展 mixins 是 Less 的一个令人兴奋的功能,它比我目前能想到的任何其他功能更能生成 DRY 代码

为什么 Less 编译器不能自动“做正确的事”? 换句话说,如果我在我的代码中声明了这个 mixin:

.someMixin {
    color: red;
}

然后我像这样使用它:

#someElement {
    .someMixin;
}

为什么编译器不能足够聪明来将这个 Less 代码优化到这个 CSS 中:

.someMixin,
#someElement
{
    color:red;
}

作为用户,为什么我必须手动添加 :extends 关键字才能获得此行为? 编译器应该足够聪明,能够意识到这种优化是可以完成的,然后再去做。

就个人而言,我认为 :extends 的想法令人困惑。 “extends”关键字的整个概念的意思是:“把这个东西 X 加上 A、B 和 C。” 但是在这种情况下,你建议重新定义扩展为:“这个东西X实际上和Y是一样的,所以你可以声明Y和X相等并写一次。” 这违背了“扩展”某些东西的标准概念。

是的,我之前也在考虑同样的事情并打算发布它,但在考虑之后决定自动将“扩展行为”应用到 mixins 对 Less.js 来说太固执了。 具体来说,尽管选择器继承 (extend) 是一个很棒的概念,对代码缩减非常有益,但我读到的关于该功能的绝大多数抱怨是它增加了一个抽象层,这使得梳理代码变得困难并在出现问题时进行调试。

伟大的思想都一样,但我个人反对这个想法,因为 a) 在extend功能完全稳定并且规范更完整之前,我们根本不应该弄乱“正常”mixin,b)我认为许多开发人员都想为自己发出这样的呼吁,并且 c) 通常事情看起来如此明显和枯燥,而事实是我们忘记了许多关于 mixin 的怪癖,这些怪癖会让你的建议至少难以实施,并且可能无法实施,同时仍然使开发人员能够使用我们已经……嗯,他们已经开始了解和喜爱的所有“混合黑客”。

:extends() 语法仍然是一个非常笨拙的技巧,不直观且难以向新用户解释。

更好的解决方案是在用户选择合适的输出样式(压缩、优化等)时,简单地让编译器自动优化上述 CSS。 如果用户选择未压缩的输出样式,则编译器应避免这些优化并生成更少的 DRY 代码。

另外,您可以使用源映射解决调试困难。 他们可以很容易地指出来自 Less mixin 的已编译 CSS 的位置。

@bdkjones请创建一个“自动优化 CSS”的新功能请求,并提供有关如何在代码中完成此操作的建议。 这种输入总是受欢迎的。

点了! 我上次的评论并不是有意如此严厉。 我有时会得意忘形。

至于代码,恐怕我完全忙于 CodeKit。 我让你们算出语言!

一点也不! 真的,我看到你在参与 CodeKit,希望得到你的持续投入。 并非所有功能都会让所有人满意,但反馈和强烈意见是唯一能让车轮转动的因素!

@bdkjones问题是级联。 在您的用例中,它可以工作,但选择器分组在所有情况下都不会产生所需的结果,因为它可能会在文档中“更早”移动选择器,从而防止覆盖这些选择器的声明。

但是,我同意你反对 mixin 扩展语法的说法,因为它在这里发展。 Selector X 应该扩展 Selector 或 mixin Y,所以这看起来很奇怪:

.border-radius(9px):extend;

我认为我们滥用了扩展语法。 如果存在的扩展语法不适合混合(这是完全合理的),我建议我们为混合找到正确的语法,而不是像@bdkjones指出的那样以破坏隐喻的方式扩展扩展语法出去。

我认为我们滥用了扩展语法

我不同意。 如果有效,请使用它。 为什么要无缘无故地创建新语法? 我认为我们对提议的语法有很好的先例,我在我的建议背后给出了大量的例子和支持理由,但你对提议的语法的看法似乎非常主观。 既然您最近多次发表过这样的声明,您能否解释一下您认为语法被滥用的原因? 或者解释在什么时候语法被滥用? 或者分享你对 mixin 应该如何扩展但没有“扩展”语法的想法?


在您的用例中,它可以工作,但选择器分组在所有情况下都不会产生所需的结果,因为它可能会在文档中“更早”移动选择器,从而防止覆盖这些选择器的声明。
...
我认为我们滥用了扩展语法。 如果存在的扩展语法不适合混入(这是完全合理的),我建议我们为混入找到正确的语法,而不是像 bdkjones 指出的那样以破坏隐喻的方式扩展扩展语法.

不。他没有指出任何东西,他敦促我们让 Less 更容易使用——这是他的底线。 他建议的这样做的方式被误导了,但意图是好的。 他没有想到的是你刚刚指出的级联。 一般使用扩展时,您必须考虑级联。 我认为任何使用扩展而不是 mixin 的人都知道这一点。 因此,这就是为什么 Less.js 为您提供了在有意义时使用它或在没有意义时 _not_ 的选择。 CSS 中的第一个“C”代表级联这一事实并没有否定在级联不是实质性的情况下合并重复样式的优势。 我在这里缺少什么?

所以你能澄清一下你的情绪吗? 你反对这个功能,还是语法? 如果您反对语法,那么请提出其他建议以保持进展,否则让我们不要阻碍对该语言有希望的功能的进展。

你反对这个功能,还是语法?

我绝对是为了这个功能。 这是一个明显的方向。 我在此线程中再次查看了语法。 一些想法:

首先,这对我来说很尴尬:

.something:extend( .clearfix() ) { }

双括号很奇怪。 但是,它忠实地采用了现有的扩展语法,因此足够公平。 所以,这就是为什么我提倡其他东西,也许是扩展以外的东西。

然后就是你提出的这个,我认为出于类似的原因:

.border-radius(9px):extend;

...我对此有过敏反应,因为它似乎与现有的扩展规范相反。 所以这对我来说似乎是误用。

我意识到那里实际上有两种选择。 一是我们对 mixin 做了一些不同的事情。 但另一种选择是我们修改现有的扩展规范,包括mixin,例如:

#namespace {
  .box-template {
    .subelement {
      // we'll add the all flag to extend everything here
    }
  }
}
.clearfix() {
  // a clearfix mixin
}
.text-shadow(@shadow) {
  -moz-text-shadow: @shadow;
  text-shadow: @shadow;
}
.some .random .selector {
  // with properties
}
.mybox {
  .clearfix:extend;
  #namespace > .box-template:extend !all;
  .text-shadow:extend(2px 2px #ff0000);
  .some .random .selector:extend;
}

但是......使用完整的选择器( .some .random .selector ),它开始读取错误。 看起来只有 .selector 有扩展名。 “扩展”这个词开始消失,因为它是本声明中的重要词。 当它被写成&:extend()时,情况并非如此(因为它出现在开头),但是这种语法似乎被 mixins 破坏了。

因此,我会提出以下选项之一:

// Migrating existing syntax, but ommitting a parens requirement when used with &:

.mybox {
  &:extend .clearfix;
  &:extend #namespace > .box-template !all;
  &:extend .text-shadow(2px 2px #ff0000);
  &:extend .some .random .selector;
}

// Adopting something similar to the SASS approach

.mybox {
  <strong i="24">@extend</strong> .clearfix;
  <strong i="25">@extend</strong> #namespace > .box-template !all;
  <strong i="26">@extend</strong> .text-shadow(2px 2px #ff0000);
  <strong i="27">@extend</strong> .some .random .selector;
}

我认为围绕扩展 mixin 和媒体查询的讨论强调了我们对:extend原始语法方法并不那么灵活,尤其是当我们想要扩展多个选择器和 mixin 时。

我认为 :extend 正确很重要。 如果我们想对mixin 使用“extend”,那么我认为我们必须修改extend 语法。

我没有提出.border-radius(9px):extend;@DesignByOnyx 提出了。 我提议.border-radius:extend(9px);

但是这两种语法对我来说都很好。 或者我们可以做.border-radius(9px) !extend;.border-radius:shamallamadingdongscoobiedoo(9px):extendmyass (jk),这对我来说并不重要,因为 mixin 或扩展的行为没有任何改变。

所以我不确定你是如何想到需要做所有这些的,你可能让自己的事情变得过于复杂。

此功能请求明确表示能够将 mixin 的继承属性复制到 mixin_ 的位置,并且它将遵循与当前 mixin 行为已经很好地建立的规则,现在也具有优先级和相同的行为<strong i="14">@import</strong> (reference)功能(顺便说一句,我已经在实践和爱中使用了很多)。 简而言之:

  • 当您使用 mixin 时,它的属性会被复制到调用 mixin 的选择器的位置。
  • 当您使用扩展时,_extending_ 选择器被复制到 _extended_ 类的位置。
  • 因此,当你扩展一个 mixin 时,调用选择器 get 被复制到 mixin 的位置。

我不知道为什么你甚至想在经过两年的辩论,> 100 篇帖子,大量研究后重新讨论关于扩展语法的辩论,并且已经证明它比@extend灵活_多得多_

顺便说一句,我不确定你在这里的意思:

使用完整的选择器(.some .random .selector),它开始读取错误。 看起来只有 .selector 有扩展名。 “扩展”这个词开始消失,因为它是本声明中的重要词。

我不同意它令人困惑,因为这就是它现在的实际运作方式。 这不是说“CSS 开发人员不知道分组选择器是如何工作的”吗? :hover:after呢? 我认为 CSS 开发人员可以很好地解决这个问题,因为它的工作方式与其他伪代码相同。

.some .random .selector:extend(.something) {}

我喜欢它提供的灵活性,因为我可以(或两者)将扩展应用于选择器,即.some .random .selector ,而不是.selector ,或者我可以将它塞进选择器块中。

我认为围绕扩展混合和媒体查询的讨论

我关闭了媒体查询问题,因为我意识到它可以通过扩展 mixin 来解决。 “条条大路通___”扩展mixin。 ;-)

我想投入我的两分钱,说括号内的括号 - :extend( .some-mixin() ) - 并没有真正打扰我,特别是因为:extend( .some-selector )已经建立并且已经被讨论得令人作呕。 我同意双括号无论如何都不理想,而且它_确实_感觉有点奇怪。 但我觉得混合和选择器在“扩展”方面的处理方式很重要,就像经典 Less 中处理它们的方式一样:

header {
    .some-selector;
    .some-mixin;
    .some-mixin();
}

因此,我并不会因为这样做而感到太糟糕(或受到限制):

header {
    &:extend( .some-selector );
    &:extend( .some-mixin );
    &:extend( .some-mixin() );
}

但我觉得混合和选择器在“扩展”方面的处理方式很重要,就像经典 Less 中处理它们的方式一样

在这一点上,我在同一页面上。

我不知道为什么你甚至想在经过两年的辩论后重新讨论关于延长语法的辩论,> 100 个帖子

这不是想不想的问题。 不,我不想。 然而在当时,我们将 mixin 打乱了一些,以便稍后处理。 我只想问一个问题,我们是否确定这种语法以我们希望它适用于所有情况的方式工作。 如果我们觉得它不起作用或者它对某些用途不雅,那么重新审视这个问题并没有错。 LESS 已经存在很长时间了。 做对比快速完成更重要。

所以,我们很酷吗?

.mybox {
  &:extend(.clearfix());
  &:extend(#namespace > .box-template all);
  &:extend(.text-shadow(2px 2px #ff0000));
  &:extend(.some .random .selector);
}

括号内的括号 - :extend( .some-mixin() ) - 并没有真正打扰我,特别是因为 :extend( .some-selector ) 已经建立

是的,事实上,我们在 Less.js 中也有双括号的先例,并且使用现有的扩展语法。 并且已经建立的先例并不像我们建议的 mixin 那样容易。 目前,我们可以这样做:

.one:nth-child(5) {
  color: red;
}
// We can extend psuedos
.two:extend(.one:nth-child(5)) {
  background: blue;
}
// And attributes
.two:extend(.one, [hidden]) {
  width: 2px;
}

您甚至会在现有 CSS 语法中找到嵌套括号。

所以这里我们有 _nested parens_ 和 _nested pseudo-class_ 语法。 我对此没有任何问题,很明显 IMO。

所以我同意@DesignByOnyx ,这是我最初的提议,出于某种原因,它在其他人看来令人反感,所以我试图找到另一种语法。 但我完全赞成在扩展的括号内使用常规的旧混合语法。

事实上,原始语法将允许扩展多个逗号分隔的类或 mixin。

.banner {
    &:extend(.clearfix(), .border-radius(4px), .alert, .navbar-fixed-top, [hidden]); 
}

它完成了工作,而且很紧。 这里没有抱怨。

所以,我们很酷吗?

是的。 完全地。 这已经是它在 CSS 中的方式了。 所以我很好。

是的。 完全地。 这已经是它在 CSS 中的方式了。 所以我很好。

就这样吧。

问题,我认为我们目前不支持 :extend 中的多个选择器,所以我想知道“all”关键字适合该格式的位置,但这可能应该是一个单独问题的一部分。

施林克特先生,你已经做到了。 你应该进入法律。 ;)

我认为我们目前不支持 :extend 中的多个选择器

但我们确实做到了 ;-) 我已经广泛地做到了。 之前刚刚做了这个:

.global-nav {
  // Extend and override bootstrap styles
  &:extend(.navbar, .navbar-fixed-top all, .navbar-inverse); // this works, and it's pretty handy
  &.hidden:extend(.navbar.hidden) {}
  &.visible:extend(.navbar.visible) {}
  &:hover {
    background: lighten(@brand-primary, 5%);
  }
  .navbar-brand {
    padding-left: 20px; 
  }
  .navbar-nav > .active > a {
    &, &:hover, &:focus {
      background-color: darken(@brand-primary, 5%);      
    }
  }
}

施林克特先生,你已经做到了。 你应该进入法律。 ;)

Pfft,大声笑哦,阻止你!

我只想补充一点,我认为这种语法:

.foo {
  &:extend( .bar() );
}

是很棒的。 我一点也不觉得括号难看。

但主要是我只是想让你们快点,这样我就可以在我最喜欢的预处理器中完成我在 SASS 中所做的所有很酷的事情:D

感谢您的反馈, @mgerring

+1 正在等待此功能。 保持良好的工作 :)

转至原帖:

.clearfixed {
   // stuff
}
.clearfix() {
    &:extend(.clearfixed);
}
.navbar {
  .clearfix();
}
.banner {
  .clearfix();
}

也许这在发布时不起作用? 但这会导致非常接近您想要的结果:

.clearfixed,
.navbar,
.banner {
  // stuff
}

@aaronmw ,是的,您的示例确实如此,但该提案的关键点是能够扩展在其他地方定义的 mixin(即,当您不能或不想修改 mixin 本身时,例如其他文件,共享图书馆等)

是的,根据@seven-phases-max 的观点,这可以按照您描述的方式完成,但这不是惯用的。

是的 - 抱歉,我现在已经阅读了更多这个主题,看看我们的目标是什么。 我使用的“骨架”类只是编译输出中的垃圾,因为 .clearfixed 类永远不会在 mixin 之外被显式引用。 &:extend(.clearfix()) 现在对我来说很有意义,而且非常令人兴奋。 现在,我将处理乱丢 CSS 的骨架类。

这里的讨论很棒!

:+1:

那么我们什么时候可以期待这个功能呢? 对于像 OOCSS 这样的概念来说,创建像“抽象类”这样的结构非常有用。

  • 决定我们如何处理嵌套/范围和混合与普通类,例如
.a {
  color: green;
}
#thing {
  .a() {
    color: black;
   }
}

.b:extend(#thing .a) {}  //
.b:extend(.a) {}  // and if so is the output wrapped by #thing?
.b:extend(.a()) {}  // do I need special format to say extend only that mixin?
  • 我们处理争论吗? 我们是否将具有相同参数的 mixin 组合在一起?
  • 更改为-css-visitor 以不删除 mixin 定义
  • 让扩展访问者访问混合定义并使用新类创建新规则集

我认为最难的一点实际上是决定_确切_它应该如何工作。

决定我们如何处理嵌套/范围和混合与普通类,例如

我会尝试以这种方式解释 mixin 扩展:
.b:extend(.a(1, 2, 3)) {}行为应该等于在 'b' 的范围内创建一个匿名的非参数混合(即简单选择器),它在内部调用.a(1, 2, 3)然后以通常的方式扩展,即:

.a(<strong i="11">@a</strong>, <strong i="12">@b</strong>, @c) {
    // ...
}

.b:extend(.a(1, 2, 3)) {}

应该等于这个:

.a(<strong i="16">@a</strong>, <strong i="17">@b</strong>, @c) {
    // ...
}

#__anon_a_1_2_3 {.a(1, 2, 3);}

.b:extend(#__anon_a_1_2_3) {}

除了没有 #__anon_a_1_2_3 出现在输出中。 我认为这种方法应该使它在不发明任何特殊规则的情况下变得更简单或更直接。

因此,通过将上述概念应用于#thing .a示例,我们得到以下内容:

.a {
  color: green;
}
#thing {
  .a() {
    color: black;
   }
}

.b:extend(#thing .a) {} // since we do ignore parens on mixin call and have ...
// no plans changing this (?), it should probably create .b {color: black} 

.b:extend(.a) {}  // there's only one .a in this scope so it's -> .b {color: green}

.b:extend(.a()) {}  // same as above -> .b {color: green}

另一方面,从实用的角度来看,“可选括号”是非常小的事情,所以也可以让它更严格并要求extend内的参数混合的括号(没有压力extend继承普通的 mixin 调用语法,因为它无论如何都不会完全兼容)。

我们是否将具有相同参数的 mixin 组合在一起?

理想情况下是的,否则会使整个事情变得无用,例如:

.b:extend(.a()) {}
.c:extend(.a()) {}

应该创建:

.b, .c {color: green}

嗯,看起来合并将是最难实现的事情。


另一个问题是范围,正如最近在 #1730 中出现的那样,mixin 使用“相对”范围路径,而扩展使用“绝对”,因此在将两者结合时我们会遇到某种冲突:

.div {color: green}

body {
   .div {color: red}

   p-a       {.div()}    // -> body p-a {color: red}
   p-b:extend(.div)   {} // -> body p-b {color: green}
   p-c:extend(.div()) {} // -> ???
}

如果我们用参数化的 mixins 重写这个例子,那就更令人困惑了。

我想献出我的两分钱,说这可能是退一步说“应该如何使用扩展 mixin”的好时机——我认为@donaldpipowitch说它带来了一点 OOCSS 能力是对的. 因此,我认为我们不应该对子类(“属性”,如果你愿意的话)如何从类本身内部扩展而陷入困境。 例如,用户将拥有某些具有“属性”(嵌套选择器)的“类”(组件):

.dog() {
    .leg { ... }
    .ears { ... }
    .fur { ... }
}

我认为我们不应该关注用户想要执行以下操作的情况:

.dog() {
    .leg { ... }
    .ears { ... }
    .fur { ... }
    .tail:extend( .leg() ) { 
        .toes { display:none; } 
    }
}

这不仅是 IMO 的边缘案例场景,而且用户无论如何都应该像这样编写他的样式:

.dog() {
    .leg, .tail { ... }
    .ears { ... }
    .fur { ... }
    .tail .toes { display:none; }
}

扩展 mixin 的 99.8% 用例是允许开发人员拥有大量的 LESS 库,其中包含他们多年来积累的样式。 这个庞大的图书馆将充满以下内容:

.clearfix() { ... }
.modal() { ... }
.alert-box() { 
    &:extend( .modal() ); 
    &.message { ... } 
    &.warning { ... } 
    &.error { ... } 
}
.grid-wrap() { ... }
.form-input() { ... }
.form-select() { ... }
.button( <strong i="16">@bgColor</strong>, <strong i="17">@textColor</strong> ) { ... }
[... thousands more like this ...]

他们可以专注于写作风格:

.page-wrap:extend( .grid-wrap(), .clearfix() ) { ... }
input[type="text"]:extend( .form-input ) { ... }
textarea:extend( .form-input() );

如果他们愿意,他们甚至可以这样做,并且最终输出中甚至不会出现任何“模态”样式,因为它们未在此项目中使用:

.inline-error:extend( .alert-box.error )

是的,我觉得@DesignByOnyx 有道理。 我不认为以后弄清楚更复杂的东西有什么问题。 事实上,我认为现在最好先实现扩展 _just non-parametric_ mixins。 这可能会覆盖所有用例的 80-90%(允许样式表使用更多面向对象的结构等)。 其他一切都可以等待一两个补丁,imo。

@DesignByOnyx@calvinjuarez我们不能在以后解决这个问题..它必须以一种或另一种方式编码。 如果我们跳到一个解决方案然后决定稍后更改它,我们会引入破坏性更改,这并不好。

如果我们能找到一种不支持边缘场景的方法,我非常高兴,这就是我们最终使用主要扩展支持所做的事情(如果需要,可以通过更多关键字进行扩展),但我们需要一个支持什么以及如何支持的计划。

@seven-phases-max 在上述情况下,我很乐意暂时忽略参数混合。

嗯,看起来合并将是最难实现的事情。

  • 但它正在合并? 我会使用与现有扩展相同的方法,例如它找到一个匹配项并将其附加到它上面......所以它并没有合并那么多,而是将两个扩展放到第三个地方,mixin,然后作为一个特殊的输出genCSS 中的案例

我还认为 @seven-phases-max 的第二个关于作用域的例子很可能会影响到某人——你只需要一个混入和同名的空参数混入。

@lukeapage :+1: 是的,我可以挖掘它。 好决定。

实际上,我认为@seven-phases-max 是正确的。 所以 :+1: 也有。

@lukeapage - 我并不是要提倡“一种或另一种”类型的解决方案,而是一种(如您所说)不支持边缘案例的方法。 事实上,我们已经超越了“本地”作用域的能力,进入了 IMO 的“来不及回去”阶段,因为:extend是这样工作的:

.block { color: green; }

.component {
  .block { color: red; }    
  div:extend( .block ) {};
}

/*
.block,
.component div {
  color: green;
}
.component .block {
  color: red;
}
*/

我不认为以下代码的工作方式与上述代码有任何不同 - 好处是最终输出中没有.block类:

.block() { color: green; }

.component {
  .block() { color: red; }  
  div:extend( .block() ) { };
}

/*
.component div {
  color: green;
}
*/

顺便说一句,我们的命名约定有轻微的偏差:) 例如,对我来说,“参数混合”是指用括号定义的任何混合,包括那些参数.mixin() {}混合(即.mixin {} )。 到目前为止,我想这种漂移并没有造成任何误解(例如,在上面的大多数示例中,如果.mixin() {}被称为“非参数”mixin,则从上下文中可以清楚地看出),但是......
不要错过在文档中一个简单的选择器也被命名为“mixin”(一旦它被混合),它也是一个“非参数”的设计混合。 因此,仅将.mixin() {}称为“非参数”可能非常含糊(从技术上讲,区别在于定义括号的存在或缺失,而不是参数的数量)。
好的,这是我平时的嘘声。 :)

@lukeapage

我很乐意暂时忽略参数化混合。

即不支持扩展具有非零参数的 mixin? 我没问题。 我只是想估计如何实现它(以统一的方式不分隔零和非零参数混合,这样当/如果后者最终跳入时它不会成​​为阻碍)。

但它正在合并? 我会使用与现有扩展相同的方法,例如它找到一个匹配项并附加到它上面..

是的,我想我更多地考虑了将 mixin 的扩展与实际 args 合并可能遇到的困难。:例如:

.b:extend(.a(1, 2, 3)) {}
.c:extend(.a(1, 2, 3)) {}

另一方面,我怀疑零参数混合也有隐藏的惊喜,例如:

.a {color: red}
.a {width: 2px}

.b:extend(.a) {}   // creates two `.b` blocks (it is expected since there're two `.a` blocks anyway)

.c {.a}            // creates one `.c` block (OK, this is just how mixins work)

.d() {color: blue}
.d() {width: 10px}

.e {.d()}          // creates one `.e` block (OK, this is just how mixins work)

.f:extend(.d()) {} // tada! another room for complains if this creates two `.f` blocks :)

好吧,也许这太深入了(而且目前也太小而无法关注)。

.f:extend(.d()) {} // tada! another room for complains if this creates two .f blocks :)

考虑到“因为在这个例子中, .d()是参数化的,它不应该创建两个.f块”?

是的,我可以理解您的观点,因为 mixin 会导致:

.f {
  color: #0000ff;
  width: 10px;
}

恕我直言,如果按步骤进行操作是有意义的,也许只是解释一下,但我不会_不_实施某些事情来避免投诉本身。 当然,这只是我的2c。 如果它是用你描述的行为实现的,你可以 - 在添加功能时 - 还可以创建一个“从扩展选择器合并 CSS 块”的功能请求,只是为了避免抱怨......?

但我不会为了避免投诉本身而实施某些措施。

我绝对同意。 我只是想预测任何可能成为“来不及改变”的惊喜。

:+1: 是的,我喜欢你的想法!

我喜欢这个讨论仍在继续。 让我回到这次讨论的一些要点。 首先,就一般用法而言,这是平等的。

.mixin {} == .mixin() {}

除了 .mixin { } 将输出作为一个类。 我知道在解析器中它们可能会受到不同的对待,但在使用中,它们会转储属性/值对。

意义:

.mixin1() {
    color: red;    
}
.mixin2 {
    color: blue;
}
.use1 {
    .mixin1;
    foo:bar;
}
.use2 {
    .mixin2;
    foo:bar;
}

由于这个 Less 语法历史,我可以这样做是有道理的:

.mixin1() {
    color: red;    
}
.mixin2 {
    color: blue;
}
.use1 {
    &:extend(.mixin1);
    foo:bar;
}
.use2 {
    &:extend(.mixin2);
    foo:bar;
}

对我来说,这是没有争议的,正如我们经常谈论的 :extend 作为许多原始 mixin 用法实例的直接替代品。

对于外行来说,这可能在直觉上是相同的,因为 .mixin1 历史上可以通过以下方式引用,无论它是否带有括号:

.use1 {
    &:extend(.mixin1);
    foo:bar;
}
.use1 {
    &:extend(.mixin1());
    foo:bar;
}

所以,我希望这样:

.mixin1() {
    color: red;    
}
.use1 {
    &:extend(.mixin1());
    foo:bar;
}
.use2 {
    &:extend(.mixin1());
    bar:foo;
}

...输出...

.use1, .use2 {
    color: red;    
}
.use1 {
    foo:bar;
}
.use2 {
    bar:foo;
}

如果 mixin 被定义了两次,它在扩展时会被替换两次,就像它的姊妹类选择器一样。

.mixin1() {
  color: red;
}
.mixin1() {
  width: 30px;
}
.use1 {
  &:extend(.mixin1);
  foo: bar;
}
.use2 {
  &:extend(.mixin1);
}
//output

.use1, .use2 {
  color: red;
}
.use1, .use2 { 
  width: 30px;
}
.use1 {
  foo: bar;
}

如果您要删除 mixin 定义上的括号,这基本上就是现在扩展的工作方式,当然,mixin 名称将出现在输出中,因此遵循现有的扩展行为是有意义的。

使用参数(我的 90% 用例),同样的事情,除了它们通过输入区分:

.col(@width) {
  width: @width;
  display: table-cell;
}

.col1:extend(.col(10%)) { }
.col2:extend(.col(10%)) { }
.col3:extend(.col(80%)) { }

//output 

.col1, .col2 {
  width: 10%;
  display: table-cell;
}
.col3 {
  width: 80%;
  display: table-cell;
}

对我来说,扩展 mixin 的原因是对参数进行分组,从而产生更强大的 mixin 库,可以产生非常简洁的输出。 将它们用于没有参数的 mixin 并不是那么重要,因为我现在可以只使用现有的 Less 特性来产生所需的结果。

感谢大家继续推动这一进程。 我认为这可能是一个非常强大的补充。

:+1 感谢@matthew-dean 的全面细分 - 我同意你所涵盖的一切。 您能否就这个场景提出您的意见,这是最近讨论的主题之一:

.mixin() { color: red; }

.component {
    .mixin() { color: blue; }

    > li:extend( .mixin() ) { ... }
}

LESS 目前的工作方式是,只有全局范围内的 mixin 会得到扩展——这意味着红色样式会得到扩展。 我个人对这种行为没有意见,虽然有人可能会编写上述代码并期望蓝色样式占上风,但我认为 extends 的“全局”行为是文档中的单行。

// this is ".mixin()", which is being extended
.mixin() { color: red; }

.component {
    // this is ".component .mixin()", which is not. 
    .mixin() { color: blue; }

    > li:extend( .mixin() ) { ... }
}

我认为 extends 的“全局”行为是文档中的单行。

完全同意。 我认为在这里引入灰色区域是一个糟糕的主意。

对我来说,重要的是一致性。 如果当前行为不扩展本地范围内的选择器,也不应该使用 mixins。 如果我们稍后在本地扩展选择器,那么 mixin 也应该如此。 人们应该能够信任库范围内的 :extend 模式。

(虽然我可以更简洁地说:“+1 @jonschlinkert的评论”。;-)

在这一点上,任何人都可以提供一个用例来使这个功能变得混乱吗? 请从@matthew-dean 的全面概述开始,然后尝试提供未涵盖的真实情况。

节日快乐。 圣诞节快乐。 菲利斯嘉年华!

非常好的概述。 我同意@matthew-dean 和所有以下评论。 :+1:

我也同意@matthew-dean。 他看起来像个壮汉,我想和他握手。

(-匿名的)

@matthew-dean 词。 :+1:

有了这个功能,我们可以让 Bootstrap 的网格系统代码变得更加清晰!

:+1:同意@cvrebert! 会好的!

刚刚重温。 我认为我们几乎达成共识,只需要实施,对吗?

我试图找到更多关于此的信息,但这就像一个阅读所有内容的迷宫。 这曾经得到实施吗? 如果是这样,有人可以将我指向文档中的适当区域。

@josh18不,当功能请求仍处于打开状态时,这通常意味着它尚未实现。

好的,谢谢,我想我会仔细检查以防万一我遗漏了什么。

我计划在某个时候总结 Wiki 中开放/将要实现的功能,但还没有时间。

我计划在某个时候总结 Wiki 中开放/将要实现的功能,但还没有时间。

@马修院长+1

嗨,大家好! 据我了解,此功能与 SASS 占位符有些相似。 只是想知道什么时候实施?

你好,
我发现很难预测我的时间和其他贡献者
实施他们感兴趣的事情,所以我不确定。 我只能说
我们确实认为它是高度优先的,它是我清单上的下一件大事。

谢谢您的回答。 期待看到这个实施和工作。 :)

+1 此功能。 它对减少 CSS 大小非常有帮助。

+1 此功能。

+1 此功能。

+1 有兴趣观看,谢谢!

:+1:

自创建此问题以来已经过去了两年。 自 2014 年 11 月以来的高优先级标记。里程碑是 1.6.0 或 2.0.0。 伟大的。 现在少了 2.5。

@Grawl

你的意思是你准备好做公关了吗?

@seven-phases-max 这几乎是我的想法。 这样的权利显示。 ;)

@seven-phases-max 大声笑不,我只是前端/设计师。
@Celc看起来真的很糟糕😅

自创建此问题以来已经过去了两年。

是啊,反正我付钱给你们是为了什么? ;-)

可悲的是无法帮助参与,但我高度赞成这个请求!

这是构建复杂有效框架的极其重要的功能

3 年和计数。 幸运的是,Sass v4 即将到来(带有sass-*前缀函数),我可以摆脱 Less。

@stevenvachon我们对 Sass 没有怨恨。 当然,它们在某种意义上是竞争对手,但项目有不同的理念,试图通过调用它们来伤害我们是毫无意义的。

当然,任何人都欢迎拉取请求。 我们很乐意将功能拉取请求与此功能合并。

我不是想伤害任何人,事实上可能是想防止这种情况发生。 我认为最好表达一个人的感受以及他们可能因此采取的新方向。 我认为早知道总比晚知道好; 在大家离开之前。 例如,Bootstrap v4 不会使用 Less.js,我相信这会对您的用户群造成很大影响。 当然,你可以随心所欲地忽略这种政治。

@stevenvachon为什么这么:extend 功能,可以满足我的所有需求。 我什至不知道为什么这个问题仍然是开放的。

哎呀,我是 Rails 开发人员,当它不是 ruby​​ 项目时使用 gulp+LESS。

题外话? 这个功能已经 3 年没有实现了,它会非常有用。

我更希望 Sass 是用 JS 编写的,但事实并非如此,而且这不是最重要的。 它的特点是。 Sass 允许我们扩展占位符,但 Less 不允许我们扩展 mixin。

伙计,这根本不是题外话,而是备受期待的功能! (尽管出于各种原因,我还是希望少一点)

它只是乞求制作。

PS 在我的例子中,我实际上只是一些 js 知识的设计师,主要是与 dom 相关的东西,与可以为 less.js 代码库做出贡献的开发人员相去甚远。无论如何,这都是一个悲伤的故事)

只是一个非常感兴趣的项目支持者)

公共服务声明

在任何时候,你都可以提交一个拉取请求,或者与开发人员合作来获取一个,并且这个特性很可能被合并。Less.js 库需要更多来自像这个线程中的人这样的个人的定期贡献. 这不是任何人的责任。 这完全取决于一个人看到这个线程,或者需要这个功能,并花时间实现它。

如果您的回答是您不是开发人员,那么您可以通过许多其他方式以非开发角色支持该项目,无论是为新功能提供所需的文档,还是在网站上设计支持、运行测试、提供反馈关于问题,项目管理,在 Stack Overflow 上回答问题,撰写博客文章,发布关于 Less 的推文,为 CSS 和网络社区做出贡献,以及编写 Less 库。

其中许多任务是由开发人员完成的,因此他们可以为开发做出贡献的时间都花在了这些其他任务上。

如果您_是_一名开发人员,而您的回答是“我没有时间”,那么这就是此问题悬而未决的确切原因。 功能是否完成由您 100% 决定,所以询问为什么“某人”没有完成它是没有用的。 _你就是那个人。_它会发生,我_保证_它会发生,如果你参与这个项目。 您可以参与网络上最流行的开源工具之一。 你可以改变......成千上万的生活? 数十万? 百万? 作为附带的好处,您可以确保您最喜欢的功能早日出现。

如果您希望此或任何功能发生,请使其发生。 我们很想拥有你。 我们很乐意与您合作! 随着社区的发展,越少越好,越少越好!

而且,听着,我很欣赏有时人们真的完全没有时间做出贡献,但仍然真的希望某个特定功能发生。 没关系。 我只想说,如果你处于那种情况,你的目标是对人们付出时间(有时是金钱)来帮助你的同情和感激,我相信 Less 社区的其他人会尽最大努力继续这样做,因为他们有能力。

真挚地,
Matthew Dean,Less.js 核心团队成员

我已经支持我自己的项目,我会听取他们的功能请求。 老实说,我没有时间深入研究 Less.js 核心。

对于那些来这里寻求 sass 占位符(或“静默类”)支持的人,请阅读此评论。 它不会让你一路走到那里(由于#1851 并且这些类不在“引用”文件中),但总比没有好。

此页面是否有帮助?
0 / 5 - 0 等级