2012-12-27 7 views
5

In Ruby, si può facilmente passare una variabile da all'interno di un metodo nel blocco codice allegato:Passare una variabile dall'interno di una dichiarazione di mixin nel blocco di contenuti allegato?

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 

Vorrei fare la stessa cosa in 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) 

Questo codice won funziona perché $ i è dichiarato all'interno della dichiarazione di mixin e non può essere visto all'esterno, dove viene utilizzato il mixin. :(

Quindi ... Come faccio a leva finanziaria variabili dichiarate all'interno della dichiarazione mixin?

Quando lavoro con un quadro di griglia e di media query, ho bisogno di questa funzionalità male. Attualmente ho duplicare cosa c'è dentro la dichiarazione mixin ogni volta ne ho bisogno, violando la regola DRY.

UPD 2013-01-24

Ecco un esempio di vita reale.

ho un mixi n che cicli attraverso i punti di interruzione e applica il codice fornito una volta per ogni punto di interruzione:

=apply-to-each-bp 
    @each $bp in $bp-list 
    +at-breakpoint($bp) // This is from Susy gem 
     @content 

Quando uso questa mixin devo usare questo valore bp $ all'interno @content. Potrebbe essere simile a questo:

// 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 

Ma questo non funzionerà, perché il valore di $ bp non è disponibile @content all'interno.

Dichiarare la variabile prima di chiamare il mixin non sarà di aiuto, perché @content viene analizzato una volta e prima che il mixin venga analizzato.

Invece, ogni volta che ho bisogno che, devo fare due brutti cosce:

  1. dichiarare un mixin ad-hoc,
  2. scrivere il ciclo, violando il principio 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) 

Quindi, la domanda è: c'è un modo per fare questo stile Ruby?

risposta

1

Questo al momento non è disponibile in Sass.

C'è un ticket rilevante nella coda di emissione di Sass: https://github.com/nex3/sass/issues/871 È nello stato pianificato ma probabilmente non lo farà fino almeno a Sass 4.0.

4

Le variabili in Sass hanno scope. Loro sono visibili solo nel blocco sono stati creati Se si desidera che la variabile sia accessibile sia all'interno che all'esterno del mixin, esso deve essere definito nello scope globale:.

$var: 0; 

@mixin test { 
    $var: $var + 1; 
    color: red; 
} 

.test { 
    $var: 5; 
    @include test; 
    @debug $var; // DEBUG: 6 
} 

Finché non preoccuparti per lo stato di $var per molto tempo, questo dovrebbe funzionare ok per i vostri scopi.

Per il tuo esempio, questo non funzionerà perché sembra che lo @content venga elaborato per primo.Quello che vi serve è un mixin che è scritto in modo diverso:

@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)); 
} 

Il CSS generato:

.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; 
} 

Un mixin come questo può essere alimentato un numero qualsiasi di argomenti e consente comunque di utilizzare @content se lo si desidera.

+0

Caro cimmanon, la soluzione suggerita non si applica alla situazione. Ho modificato la mia domanda iniziale per aggiungere un esempio completo e quasi reale di ciò che sto cercando. Si prega di dare un'occhiata e scrivere le vostre considerazioni. –

1

Ho incontrato personalmente questo problema e AFAIK questa è una limitazione corrente in SASS.

Problemi correlati