Sass基礎學習No.9-除了@for還有@each跟@while供挑選

@each陣列循環

Sass官網如此介紹@each:

The @each rule makes it easy to emit styles or evaluate code for each element of a list or each pair in a map. It’s great for repetitive styles that only have a few variations between them.It’s usually written @each in { … }, where the expression returns a list. The block is evaluated for each element of the list in turn, which is assigned to the given variable name.

都是英文很難理解,反正寫法就是**@each <variable> in <expression> { ... }**,所以直接看程式碼。

陣列Lists

1
2
3
4
5
$colors: red,green,blue,yellow

@each $color in $colors
.icon-#{$color}
font-size: $color
1
2
3
4
5
6
7
8
9
10
11
12
/*編譯結果CSS*/
.icon-red {
font-size: red; }

.icon-green {
font-size: green; }

.icon-blue {
font-size: blue; }

.icon-yellow {
font-size: yellow; }

因為是.sass格式所以不用加{},對比一下寫法**@each <variable> in <expression> { ... }**跟上面程式碼編譯結果會發現@each的執行就是將陣列$colors裡面的值以設定的變數$color 一個一個依序帶入到下方的程式碼裡。

物件Maps

1
2
3
4
5
6
$font-sizes: ('small': 12px, 'normal': 18px, 'large': 24px)
@each $key,$val in $font-sizes
.f-#{$key}
font-size: $val
.f-#{$val}
font-size: $key
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
/*編譯結果CSS*/
.f-small {
font-size: 12px; }

.f-12px {
font-size: "small"; }

.f-normal {
font-size: 18px; }

.f-18px {
font-size: "normal"; }

.f-large {
font-size: 24px; }

.f-24px {
font-size: "large"; }

發現規律了,@each $key,$val in $font-sizes 中第一個的變數$key 就是物件$font-sizes中的key(通常稱為鍵),而第二個變數$val就是物件$font-sizes中的value(通常稱為值)。

陣列中的陣列、物件中的物件如何結合@each

陣列

1
2
3
4
5
$arr: 'small' red 12px,'normal' green 18px, 'large'blue 24px, 'xl'yellow 36px
@each $name,$color,$size in $arr
.#{$name}
color: $color
font-size: $size
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
/*/*編譯結果CSS*/
.small {
color: red;
font-size: 12px; }

.normal {
color: green;
font-size: 18px; }

.large {
color: blue;
font-size: 24px; }

.xl {
color: yellow;
font-size: 36px; }

感覺跟Maps寫法很像,但是仔細觀察發現,原來陣列中如果還有陣列的話(記得要按照一定的規則排序),在@each後面所接的 $name,$color,$size是按照陣列$arr中順序的喔!

物件

1
2
3
4
5
6
$obj: (default:( class: 'default', color: #333, bg: #fff, border-color: #ccc), primary:( class: 'primary', color: #fff, bg: red, border-color: darken(red, 0)), danger:( class: 'danger', color: #fff, bg: greem, border-color: darken(green, 0)))

@each $key,$val in $obj
.#{$key}
color: map-get($val, color)
background-color: map-get($val, bg)

物件中的物件,其實一樣是key-value的組合,只是在value裡又是key-value組合。
並且利用map-get來獲得每一組value值中欲尋找的key的值。

Q:這裡的 map-get($val, color) 與之前在[Sass基礎學習No.8]index()、nth()及map-get()快速查找陣列所教的map-get有些許差異,因為之前都是都是先創建 變數$物件名稱後面才接物件值,但是在這裡卻是直接將 $value也就是物件的值代入,這是為什麼?
A:如果賦予變數A的值是另一個變數B的話,會產生的結果是變數A往上尋找變數B,就像是 $primary:$red,$primary會往上尋找$red的值,所以如果在物件中寫出 $obj: ($default:( class: ‘default’, color: #333, bg: #fff, border-color: #ccc), $primary:(…),…),它的意思並不是在$obj中創建物件 $default或$primary,而是讓 $obj 往上找出 $default或$primary的值,但事實上並沒有這些值,因此會出現 undefined(未賦值)。

更多運用請參考
廖洧杰Sass教學 (28) - @each+Sass Maps批次新增各元素樣式
卡斯柏Sass map get

@while

Sass官網如此介紹@while:

The @while rule, written @while { … }, evaluates its block if its expression returns true. Then, if its expression still returns true, it evaluates its block again. This continues until the expression finally returns false.

@while比較像是@if@for的結合,既有判斷又有迴圈,@while <expression> { ... } 中的只要是true,就會一直執行{…}的內容,直到變false才會停止執行{…}。

1
2
3
4
5
6
$start: 6px
$end: 24px
@while $start <= $end
.item-#{$start}
font-size: $start
$start: $start*2
1
2
3
4
5
6
7
8
9
10
11
12
/*編譯結果CSS*/
.item-6px {
font-size: 6px;
}

.item-12px {
font-size: 12px;
}

.item-24px {
font-size: 24px;
}

只要$start ≤ $end為true,下方程式碼就會被執行,如果沒有這個$start: $start*2的話,那麼$start ≤ $end就會一直為true,也就是會變成無限循環(永遠沒有false),所以在使用@while時也一定要注意這一點。

結合@each跟@while

1
2
3
4
5
6
7
8
$obj: (default:( class: 'default', color: #333, bg: #fff, border-color: #ccc,font-size: 12px), primary:( class: 'primary', color: #fff, bg: red, border-color: darken(red, 0),font-size: 18px), danger:( class: 'danger', color: #fff, bg: greem, border-color: darken(green, 0),font-size: 24px))

@each $key,$val in $obj
$font: map-get($val, font-size)
@while $font<= 24px
.item-#{$key}
font-size: $font
$font: 25px //為了跳出@while
1
2
3
4
5
6
7
8
9
10
11
12
/*編譯結果CSS*/
.item-default {
font-size: 12px;
}

.item-primary {
font-size: 18px;
}

.item-danger {
font-size: 24px;
}

為了讓@while為false並跳出迴圈,所以設置了$font:25px,這樣一來才能跳出迴圈,並接下去執行@each(不過這段程式碼很多餘,只是為了呈現怎麼結合,但其實沒必要🤣)。

參考資料:
SASS詳解之控制指令(if、each、for和while)
[Sass基礎學習No.7]@for迴圈結合random()隨機省時間
[Sass基礎學習No.8]index()、nth()及map-get()快速查找陣列或物件值