為了有效的維護和開發(fā)項目,代碼的重復(fù)利用就顯得尤為重要。在Sass中,除了@import和@extend可以使你的代碼更加具有重復(fù)利用性,@mixin指令也同樣能提高你代碼的重復(fù)使用率并簡化你的代碼。
@extend指令通過繼承從而簡化了代碼,但是它也有缺陷之處,首先是不夠靈活,其次它還會將你不需要的其他地方具有相同類名的樣式都繼承過來。
@mixin指令是另一種簡化代碼的方法。Mixins可以包含任意內(nèi)容且可以傳遞參數(shù),因此比'@extend'更加靈活和強大。
定義Mixins
通過@mixin加名稱的方式就可以定義一個Mixins模塊,在模塊內(nèi)你可以添加任何你想重復(fù)使用的樣式。
@mixin button {
font-size: 1em;
padding: 0.5em 1.0em;
text-decoration: none;
color: #fff;
}
由于歷史原因,連字符和下劃線被認為是相同的,也就是說 @mixin button-large { } 和 @mixin button_large { } 是一樣的。
Mixins能夠包含任何在 CSS 和 Sass 中有效的內(nèi)容。
@mixin link {
a {
color: blue;
&:visited {
color: purple;
}
&:hover {
color: white;
}
&:active {
color: red;
}
}
}
使用@mixin指令
你可以通過@include來調(diào)用具有相同名稱的mixin模塊。
.button-green {
@include button;
background-color: green;
}
比如通過@include調(diào)用我之前創(chuàng)建名為button的mixin模塊,那么解析后的CSS就如下所示:
.button-green {
font-size: 1em;
padding: 0.5em 1.0em;
text-decoration: none;
color: #fff;
background-color: green;
}
正如你所預(yù)期的那樣,@include被名為button的混合模塊內(nèi)的樣式所取代。同時我在.button-green中添加的background-color樣式依然保留著。
在mixin模塊的定義中還可以包含其他的mixin。比如:
@mixin button-blue {
@include button;
@include link;
}
所以你可以通過以包含多種簡單mixin模塊的方式創(chuàng)建較為復(fù)雜的mixin模塊。
當(dāng)Mixins模塊包含選擇器和規(guī)則集,也就是mixins包含的內(nèi)容本身就是有效的CSS樣式時,他們就可以在其他規(guī)則集外被調(diào)用。比如本文之前創(chuàng)建的名為link的mixin模塊:
@mixin link {
a {
color: blue;
&:visited {
color: purple;
}
&:hover {
color: white;
}
&:active {
color: red;
}
}
}
之后我們可以直接調(diào)用這個模塊,即使不在一個選擇器內(nèi)。
@include link;
這段代碼將會被解析為:
a {
color: blue;
&:visited {
color: purple;
}
&:hover {
color: white;
}
&:active {
color: red;
}
}
之所以能這樣調(diào)用是因為這個mixin模塊內(nèi)既包含了選擇器也包含了樣式,如果沒有選擇器,那么編譯后將不會有內(nèi)容顯示。比如我們在選擇器外直接調(diào)用button這個mixin模塊,那么將不會有東西被編譯。
@mixin button {
font-size: 1em;
padding: 0.5em 1.0em;
text-decoration: none;
color: #fff;
}
@include button;
不會被編譯是因為你的樣式?jīng)]有被應(yīng)用到任何元素上。
參數(shù)的使用
Mixins可以接收和使用參數(shù),這使得它比@extend更加強大和靈活。我更新了之前的button模塊,增加了名為background的參數(shù)并將其傳遞給模塊。
@mixin button($background) {
font-size: 1em;
padding: 0.5em 1.0em;
text-decoration: none;
color: #fff;
background: $background;
}
注意到參數(shù)被設(shè)置為一個變量并成為backround屬性的值。如果我們想創(chuàng)建一個綠色的按鈕,那么就可以使用以下代碼:
.button-green {
@include button(green);
}
當(dāng)Sass被編譯時,值green就被傳遞給@mixin并成為變量$backround的值。編譯后的代碼如下:
.button-green {
font-size: 1em;
padding: 0.5em 1.0em;
text-decoration: none;
color: #fff;
background: green;
}
你還可以在@mixin和@include中傳遞多個參數(shù),參數(shù)間用逗號隔開。比如:
@mixin button($background, $color) {
font-size: 1em;
padding: 0.5em 1.0em;
text-decoration: none;
color: $color;
background: $background;
}
.button-green {
@include button(green, #fff);
}
給參數(shù)設(shè)置默認值
你可能會好奇如果在定義mixin時定義了參數(shù),但是在@include調(diào)用時沒有傳遞參數(shù)會發(fā)生什么。這種情況下你會收到一個編譯錯誤的提示。同時我相信這種情況一定不是你想看到的。你可以通過在mixin中定義參數(shù)的時候給它設(shè)置一個默認值,從而來避免這種錯誤。
@mixin button($background: green) {
font-size: 1em;
padding: 0.5em 1.0em;
text-decoration: none;
color: #fff;
background: $background;
}
現(xiàn)在如果你在調(diào)用的時候忘記傳遞參數(shù)值
.button-green {
@include button;
}
你的代碼將會使用你設(shè)置的參數(shù)默認值來解析,在這個例子中也就是green這個值。
.button-green {
font-size: 1em;
padding: 0.5em 1.0em;
text-decoration: none;
color: #fff;
background: green;
}
當(dāng)然,你也可以通過提供一個參數(shù)值來覆蓋這個默認值。
.button-blue {
@include button(blue);
}
這時將會使用你提供的值來編譯代碼
.button-blue {
font-size: 1em;
padding: 0.5em 1.0em;
text-decoration: none;
color: #fff;
background: blue;
}
關(guān)鍵字參數(shù)
為了幫助你的代碼更加容易理解,你可以在傳遞值給mixin時將參數(shù)名稱和參數(shù)值一并傳遞過去。
.button-green {
@include button($background: green, $color: #fff);
}
關(guān)鍵字參數(shù)會額外增加一些代碼,但是這會使得你的@include更加容易理解。比如,上面那段代碼就比下面這段代碼更加容易理解,因為上面的代碼明確指出了green和#fff分別是什么。
.button-green {
@include button(green, #fff);
}
雖然選擇器的名稱給了我們一些線索,可以大概推斷出第一個參數(shù)代表什么,但是對于第二個參數(shù)卻沒有任何提示作用,而且一年后你很可能不會再記得這個參數(shù)的含義。
一起傳遞關(guān)鍵字名稱和值也被稱為命名參數(shù),你也可以以任意順序傳遞命名參數(shù)。下面兩種傳遞方式解析后會得到相同的結(jié)果。
.button-green {
@include button($background: green, $color: #fff);
}
.button-green {
@include button($color: #fff, $background: green);
}
因為命名參數(shù)是變量名,由于歷史原因,下劃線和破折號可以互換使用。
數(shù)量可變的參數(shù)
Mixins可以接收未知數(shù)量的參數(shù)。比如你可以給同一個元素增加多種box-shadows。這里,我增加了暗灰和淺灰兩種陰影。
.container {
box-shadow: 0px 1px 2px #333,
2px 3px 4px #ccc;
}
在另一個元素上你可能只想使用一種陰影或者在其他元素上你又想使用三種或者四種陰影。這個時候你就可以創(chuàng)建一個接收數(shù)量可變的參數(shù)的mixin模塊,并且在使用@include指令的時候決定傳遞參數(shù)的數(shù)量。
@mixin box-shadows($shadow...) {
box-shadow: $shadow;
}
.container {
@include box-shadows(0px 1px 2px #333, 2px 3px 4px #ccc);
}
通過在變量名后增加三個點(...)來使mixin模塊接收數(shù)量可變的參數(shù)。需要注意的是這些是三個周期的字符,而不是單一的省略號。當(dāng)你使用@include傳遞參數(shù)的時候,使用逗號將參數(shù)分開。
之前的代碼將被編譯為:
.container {
box-shadow: 0px 1px 2px #333,
2px 3px 4px #ccc;
}
Sass將所有參數(shù)打包為一個列表,但是在此我沒有列出這個列表,相關(guān)內(nèi)容之后我會再做補充。
你同樣可以給mixin傳遞可變的參數(shù)
@mixin box-shadows($shadow...) {
box-shadow: $shadow;
}
$shadows: 0px 1px 2px #333, 2px 3px 4px #ccc;
.container {
@include box-shadows($shadows...);
}
這里我將變量'$shadows'設(shè)置為有兩種陰影的list,并在@include中將其作為參數(shù)傳遞。同樣,你也可以將參數(shù)設(shè)置為一個map,并且作為參數(shù)傳遞。你也可以同時傳遞list和map,只要list作為第一個傳遞。
@include box-shadows($list..., $map...)