在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规则。
UPD 2013-01-24
这是一个真实的例子。
我有一个循环遍历断点的mixin,并为每个断点应用提供的代码一次:
=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之前。
相反,每次我需要的时候,我必须做两条丑陋的大腿:// 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风格?
答案 0 :(得分:4)
Sass中的变量具有范围。它们仅在创建它们的块中可见。如果您希望变量可以在mixin内部和外部访问,则必须在全局范围内定义:
$var: 0;
@mixin test {
$var: $var + 1;
color: red;
}
.test {
$var: 5;
@include test;
@debug $var; // DEBUG: 6
}
只要你不长时间关心$var
的状态,这应该可以用于你的目的。
对于您的示例,这不起作用,因为看起来首先处理@content
。你需要的是一个拼写不同的mixin:
@mixin test($properties...) {
@for $i from 1 to 8 {
.grid-#{$i} {
@each $p in $properties {
$list: nth($p, 2);
@if length($list) > 1 {
#{nth($p, 1)}: nth($list, $i);
} @else {
#{nth($p, 1)}: $list;
}
}
@content;
}
}
}
.test {
@include test(color (red green blue orange yellow brown black purple));
}
生成的CSS:
.test .grid-1 {
color: red;
}
.test .grid-2 {
color: green;
}
.test .grid-3 {
color: blue;
}
.test .grid-4 {
color: orange;
}
.test .grid-5 {
color: yellow;
}
.test .grid-6 {
color: brown;
}
.test .grid-7 {
color: black;
}
像这样的mixin可以提供任意数量的参数,如果你愿意,你仍然可以使用@content
。
答案 1 :(得分:1)
我自己遇到了这个问题而AFAIK这是SASS的当前限制。
答案 2 :(得分:1)
所以这在Sass目前无法使用。
Sass问题队列中有一张相关的票证:https://github.com/nex3/sass/issues/871它处于计划状态,但可能至少要达到Sass 4.0。