摆脱Sass mixin的限制

5

是否有可能在Sass mixin中提前跳出或返回?我想做类似于这样的事情:

@mixin foo($bar: false) {

  @if $bar {
    // return early without applying any of the styles below
  }

  color: red;
}

编辑:请记住,这个例子是我能想到的最简单的东西,它说明了我的问题。在现实世界中,我的代码要复杂得多,并且对此的用例是清晰明确的。


1
为什么要为你的mixin设置break out?你可以使用@if和@else代替,查看这个gist - Alex Guerrero
1
跳出Mixin会使代码更简洁易读。请参阅https://dev59.com/tnVC5IYBdhLWcg3whRcw。 - LandonSchropp
Mixin不使用@return语句返回值,而是显示一个代码块。最好的解决方案是使用@if@else,详情请参见:https://gist.github.com/Aloge/7673360但如果您完成了示例并描述了您的场景,我可以为您提供帮助,@LandonSchropp。 - Parhum
@Parhum 真遗憾。我的问题不是我不能做到,而是我正在尝试以一种易于阅读和维护的方式来实现它。 - LandonSchropp
如果你想使用Mixin,你必须使用@if并在其中执行任何操作。看看这个mixin:http://web-design-weekly.com/blog/2013/05/12/handy-sass-mixins/只需使用if... 但是你可以使用@function吗? - Parhum
3个回答

8

Sass实际上没有“break”概念,但使用@if/@else可以接近实现:

@mixin foo($bar: false) {

  @if $bar {
    color: green;
  }
  @else {
    color: red;
  }

}

来自Sass首席开发人员的消息:https://github.com/nex3/sass/issues/378 问题在于,Sass中较少使用的控制结构越多,只是对该语言略有了解的人阅读使用这些控制结构的样式表就越困难。这就是为什么开始时只使用了最简单的一组结构来完成任何事情:因为在许多情况下,倾向于使用更小的语言范围而不是用于编写复杂代码的最佳语义。

感谢回复,特别是来自Sass维护者的评论。在我看来,语言应该以清晰为目标而不是熟悉,但这显然是正确的答案。 - LandonSchropp

1

我仍然认为在Sass中,@if/@else语句是处理问题最简单、最好的解决方案,但我创建了两个不同的拆分mixin来帮助你并作为挑战:

首先使用这个mixin进行操作

没有@includes的拆分mixin (链接)

@include breakout($styles)

$style应该是由空格分隔的样式列表,以下是允许的值:

  • 样式
    常见的CSS样式用空格分隔,不带冒号或分号,值列表应该用括号包裹:

      @include breakout(
        color blue // <属性> <值>
        width (100 * 20px) // <属性> <值操作>
        border (1px solid #fff) // <属性> <值列表>
        box-shadow (0 0 10px 4px #0000FF , 0 0 20px 30px #008000) // <属性> <嵌套值列表>
      )
    
  • Breaks
    如果条件为真,则编译断点样式,同时当条件为真时,mixin结束而不返回break值后的所有样式

      $foo: true;
      @include breakout(
        break (false color red)  // break (<条件> <属性> <值>
        break ((3 < 2) border (1px solid #fff)) // breaks也支持列表和嵌套列表
        break ($foo width 10px) // 因为条件为真,所以这个break被编译
        color blue // 这个样式没有被编译,因为$foo break结束了mixin
      )
    
请注意 mixin 参数列表的顺序非常重要,因为它决定了编译和未编译样式是否符合条件。

使用 @includes 的 Breakout mixin(链接

此 mixin 与上述 mixin 类似,但它将 $stylesbreak-mixin mixin 和 @content 的 mixin 值引入到 breakout mixin 中,以允许使用 @includes

  • Mixins
    如果你想在breakout mixin中使用其他mixin,则需要在$styles中添加一些代码,并将每个mixin添加到break-mixin mixin中。

      @include breakout(
        mixin foo // mixin <name of the mixin declared into break-mixin arguments>
        mixin bar // mixin name should match break-mixin argument
        mixin foobar
      ) {
        @include break-mixin(foo) { // 这里是你的mixin或者mixin们,用于mixin foo }
        @include break-mixin(bar) { @include mixin1; @include mixin2; @include mixin3}
        @include break-mixin(foobar) { @include foobar}
      }
    
  • Mixin breaks
    现在您还可以在breaks中使用mixin。这里顺序仍然很重要:

      $foo: true
      @include breakout(
        mixin foobar
        mixin bar
        break ($foo mixin foo) // 如果条件为true,则此breaks被编译
        color blue // 因为$foo break结束了mixin,所以不编译此样式
      ) {
        @include break-mixin(foo) { // 这里是你的mixin或者mixin们,用于mixin foo }
        @include break-mixin(bar) { @include mixin1; @include mixin2; @include mixin3}
        @include break-mixin(foobar) { @include foobar}
      }
    

因此,针对您的特定情况,请将 Breakout mixin without @includes (link)复制到您的scss文件中,或使用它作为一个部分,然后将其添加到您的代码中;

@include breakout(
  break ($bar property value) // The break out statement
  color red // If $bar != false this will be compiled if not it won't
);

1
感谢您的详细回复,但我觉得这会给代码增加一些不必要的复杂性。 - LandonSchropp

0

我很惊讶@error语句还没有被提到。根据文档(重点在于):

编写混合器和接受参数的函数时,通常要确保这些参数具有API所期望的类型和格式。如果它们不是,则需要通知用户并停止运行您的混合器/函数

话虽如此,@error可能并不适用于每种情况,因为它会完全停止Sass编译。这使得它不适用于混合器,其中退出是预期的结束场景。

Sass文档中的示例:

@mixin reflexive-position($property, $value) {
  @if $property != left and $property != right {
    @error "Property #{$property} must be either left or right.";
  }

  $left-value: if($property == right, initial, $value);
  $right-value: if($property == right, $value, initial);

  left: $left-value;
  right: $right-value;
  [dir=rtl] & {
    left: $right-value;
    right: $left-value;
  }
}

.sidebar {
  @include reflexive-position(top, 12px);
  //       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  // Error: Property top must be either left or right.
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接