В 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:
=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 объявлен внутри объявления примеси и не виден снаружи, где используется примесь. :(
Итак... Как мне использовать переменные, объявленные внутри объявления миксина?
Когда я работаю с сеткой и медиа-запросами, мне очень нужна эта функциональность. В настоящее время я должен дублировать то, что находится внутри объявления миксина, каждый раз, когда мне это нужно, нарушая правило DRY.
Обновление от 24 января 2013 г.
Вот реальный пример.
У меня есть миксин, который циклически проходит через точки останова и применяет предоставленный код один раз для каждой точки останова:
=apply-to-each-bp
@each $bp in $bp-list
+at-breakpoint($bp) // This is from Susy gem
@content
Когда я использую этот миксин, я должен использовать это значение $bp внутри @content. Это может быть так:
// 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.
Объявление переменной перед вызовом миксина не поможет, потому что @content анализируется один раз и до того, как анализируется миксин.
Вместо этого КАЖДЫЙ раз, когда мне это нужно, мне приходится делать два уродливых бедра:
- объявить специальный миксин,
- напишите цикл, нарушая принцип 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?