在 Ruby 中,您可以轻松地将方法内部的变量传递到附加的代码块中:
def mymethod
(1..10).each { |e| yield(e * 10) } # Passes a number to associated block
end
mymethod { |i| puts "Here comes #{i}" } # Outputs the number received from the method
我想在 SASS mixin 中做同样的事情:
=my-mixin
@for $i from 1 to 8
.grid-#{$i}
@content
+my-mixin
color: nth("red green blue orange yellow brown black purple", $i)
此代码不起作用,因为 $i 是在 mixin 声明中声明的,并且无法在使用 mixin 的外部看到。:(
那么......我如何利用在 mixin 声明中声明的变量?
当我使用网格框架和媒体查询时,我非常需要这个功能。目前,我每次需要时都必须复制 mixin 声明中的内容,这违反了 DRY 规则。
更新 2013-01-24
这是一个真实的例子。
我有一个混合断点循环并为每个断点应用一次提供的代码:
=apply-to-each-bp
@each $bp in $bp-list
+at-breakpoint($bp) // This is from Susy gem
@content
当我使用这个 mixin 时,我必须在 @content 中使用这个 $bp 值。它可能是这样的:
// Applies to all direct children of container
.container > *
display: inline-block
// Applies to all direct children of container,
// if container does not have the .with-gutters class
.container:not(.with-gutters) > *
+apply-to-each-bp
width: 100% / $bp
// Applies to all direct children of container,
// if container has the .with-gutters class
.container.with-gutters > *
+apply-to-each-bp
$block-to-margin-ratio: 0.2
$width: 100% / ($bp * (1 + $block-to-margin-ratio) - $block-to-margin-ratio)
width: $width
margin-right: $width * $block-to-margin-ratio
&:nth-child(#{$bp})
margin-right: 0
但这不起作用,因为 $bp 的值在 @content 中不可用。
在调用 mixin 之前声明变量将无济于事,因为 @content 在 mixin 被解析之前被解析一次。
相反,每次我需要它时,我都必须做两个丑陋的大腿:
- 声明一个临时混合,
- 写循环,违反DRY原则:
// Each of the following mixins is mentioned in the code only once.
=without-gutters($bp)
width: 100% / $bp
=with-gutters($bp)
$block-to-margin-ratio: 0.2
$width: 100% / ($bp * (1 + $block-to-margin-ratio) - $block-to-margin-ratio)
width: $width
margin-right: $width * $block-to-margin-ratio
&:nth-child(#{$bp})
margin-right: 0
// Applies to all direct children of container
.container > *
display: inline-block
// Applies to all direct children of container,
// if container does not have the .with-gutters class
.container:not(.with-gutters) > *
@each $bp in $bp-list
+at-breakpoint($bp) // This is from Susy gem
+without-gutters($bp)
// Applies to all direct children of container,
// if container has the .with-gutters class
.container.with-gutters > *
@each $bp in $bp-list // Duplicate code! :(
+at-breakpoint($bp) // Violates the DRY principle.
+with-gutters($bp)
所以,问题是:有没有办法做到这种 Ruby 风格?