sass揭秘之變量
全局變量和局部變量
要了解sass或less的變量,有必要先了解下js的變量定義,先來一段js的代碼:
var a = 1; (function(){ a = 5; })(); console.log(a);//5
上面這段代碼,匿名函數裏面的a因為沒有使用var關鍵字來定義,所以當我們在函數外打印a的時候,得到的是5,改變了一開始定義的1
var a = 1; (function(){ var a = 5; })(); console.log(a);//1
而這段代碼,匿名函數裏面的a使用了var關鍵字來定義,所以當我們在函數外打印a的時候,得到的是1,一開始定義的值。
如果你明白了上面兩個的區別,那下面就好辦了,如果你還沒有明白,那麽建議先去看下js的變量申明。 也許你現在已經看出眉目了,其實sass的變量設計用的是上面兩段代碼中的第一段思想,即在局部不使用var來申明,而less用的是第二段思想,即局部使用var來申明,這就是很多人所說的為什麽sass沒有局部變量。我們來兩段代碼測試下:
sass版
$color:red; p{ $color:blue; color:$color;//blue } a{ color:$color;//blue }
less版
@color:red; p{ @color:blue; color:@color;//blue } a{ color:@color;//red }
簡單總結下:如果全局申明了一個變量a,sass中如果使用到局部中是屬於改變a的值,所以後來所有的都是改變之後的值;而less中使用到局部變量則屬於在局部重新定義a的值,不影響其他地方。說到底,其實sass和less的變量其實都是js變量的表現形式,兩者都有其科學性,只是設計思路不同而已。
當然說到這裏,可能有人會說了,那sass就沒有局部變量嘍。其實不然,正確的說法應該是:在有全局變量的情況下,sass是沒有局部變量的。意思是如果要看到sass的局部變量,請不要設置全局變量。代碼為證:
p{ $color:blue; color:$color;//blue } a{ color:$color;//$color未定義 }
這是一個沒有定義全局變量$color的例子,上面的p元素的color為blue,而a裏面就會報錯因為$color沒定義,它沒有獲取到p元素裏面定義的那個$color變量,這證明了其實sass同樣存在局部變量,只是這個前提是得沒有全局變量。
相信到這裏,大家應該對sass的變量有所了解,不至於那麽迷惑吧。下面我們再來兩段代碼:
p{ $color:blue; color:$color;//blue a{ color:$color;//blue } }
這一段代碼中,a嵌套在p中,然後在p元素中定義了$color這個變量,a裏面是可以訪問到$color變量的。
p{ $color:blue; color:$color;//blue a{ $color:red; color:$color;//red } background-color:$color;//red span{ color:$color;//red } } div{ color:$color;//$color未定義 }
估計這裏有人迷惑了,我們來分析下吧:因為sass的代碼是從上到下解析的,所以這段代碼執行到p的color值的時候顏色是上面的blue色,然後由於我們在a中又改變了$color的值為紅色,所以後面所有p元素範圍內用到$color這個變量的都為紅色,這反應到我們後來的bgcolor和span的color上面,而p元素之外還是未定義。
這裏吐個槽吧,其實個人覺得正是由於這個,使得開發sass的小心定義變量,以避免汙染;而less呢卻剛好相反,估計到時候就是全局局部滿天飛的情況,代碼一團糟。你想選擇哪種呢?
關於sass的全部變量和局部變量就說到這,既然這篇文章的標題說了是sass變量揭秘,光這全局變量和局部變量肯定是滿足不了大家的胃口的,下面我們繼續說下sass變量的另一個創新點,變量默認值。
變量默認值!default
可能很多人對這個不是很熟悉,或者覺得這個其實就是個幌子,掛羊頭賣狗肉的家夥。其實不然,它的來頭可不小,而且是非常的科學,我是佩服的五體投地,因為它從根本上解決了困擾我多年的css組件化開發。簡單來兩段比較的代碼:
無!default
$color:red; $color:blue; p{ color:$color;//blue }
有!default
$color:red; $color:blue !default; p{ color:$color;//red }
上面說了,sass編譯css是從上到下的,後面會覆蓋前面的,所以第一段無!default的解析的是blue,而第二段代碼由於有了!default,打破了這個規則,使用了前面定義的red。有意思吧,當然這樣的使用是體現不了它偉大的價值的。
簡單介紹下它的作用吧:假設變量申明帶有!default,那麽如果在此申明之前沒有這個變量的申明,則用這個值,反之如果之前有申明,則用申明的值。當然如果你先!default申明,然後再申明一次,那就沒什麽意思了,這就是基本的變量覆蓋,第一次申明的有無!default都一樣。所以你要區分這兩種情況:
//第一種,使用默認值
//變量申明帶有!default,但是之前沒有這個變量的申明
$color:blue !default; p{ color:$color;//blue }
//第二種,使用前面定義的值
$color:red;
//變量申明帶有!default,但是前面還有這個變量的申明
$color:blue !default; p{ color:$color;//red }
//第三種錯誤的用法,先!default申明
$color:red !default; $color:blue;
上面的第三種錯誤用法其實和下面的這個覆蓋寫法是一樣一樣的:
//覆蓋寫法
$color:red;
$color:blue;
能一口氣看到這裏的,應該有點時間,建議簡單活動下,搖搖腦袋,伸伸懶腰,因為下面的更加精彩。
其實長久以來,css之所以不能組件化開發,有兩大原因:第一個是@import的樣式不能合並在一個文件中(這裏排除使用壓縮工具來合並);第二個問題就是這裏說到的變量問題了。感謝sass幫我們全解決了,大笑三聲。
現在假設我們有個scss文件,這裏暫且叫做_imgstyle.scss
,代碼如下:
// 變量 //--------------------------------- $imgStyleBorder: 1px solid #ccc !default; $imgStylePadding: 2px !default; $imgStyleRadius: 8px !default; // mixin //--------------------------------- @mixin img-border($border:$imgStyleBorder,$padding:$imgStylePadding){ border: $border; padding: $padding; } @mixin img-rounded($radius:$imgStyleRadius){ border-radius:$radius; } //樣式 //--------------------------------- .img-border{ @include img-border; } .img-rounded{ @include img-rounded; }
接下來我們要在style.scss
這個文件裏面調用_imgstyle.scss
,代碼如下:
//導入_imgstyle.scss
@import ‘imgstyle‘;
現在問題來了,如果我們對默認的padding為2px不滿意,要改為5px,我們有如下方法:
方法一:重新覆寫
//導入_imgstyle.scss @import ‘imgstyle‘; .img-border{ padding:5px; }
解析成的css:
.img-border { border: 1px solid #cccccc; padding: 2px; } .img-rounded { border-radius: 8px; } .img-border { padding: 5px; }
方法二:改變@include的參數
//導入_imgstyle.scss @import ‘imgstyle‘; .img-border{ @include img-border($imgStyleBorder,5px); }
解析成的css:
.img-border { border: 1px solid #cccccc; padding: 2px; } .img-rounded { border-radius: 8px; } .img-border { border: 1px solid #cccccc; padding: 5px; }
顯而易見,上面的方法都會產生重復的代碼,不科學啊。當然這時候可能有人會說了,你腦子浸水了唄,直接在_imgstyle.scss
文件中,修改$imgStyleBorder
為5px不就得了。當然如果你要的是每個項目使用這個樣式的時候都拷貝一份這個,然後打開把變量修改成你要的值,那麽我只好承認我腦子浸水了,不僅腦子浸水,還得吐血了。
現在請上面那些山寨土鱉方法閃一邊去,該我們的!default出場了,廢話少說,上代碼:
//申明$imgStylePadding為5px $imgStylePadding: 5px; //導入_imgstyle.scss @import ‘imgstyle‘; 解析成的css: .img-border { border: 1px solid #cccccc; padding: 5px; } .img-rounded { border-radius: 8px; }
無須去源文件中修改,且解析出來無重復代碼,完美!這才是!default的價值,這為組件式開發,更改調用組件裏面的變量的值帶來了徹底的變化。如果less真沒有這個變量的默認值的話,那less的同學們估計得傷心死了。
重量級的都介紹完了,下面把其他的一些小羅羅也簡單介紹下吧。
變量後面加...
在css3出現以前,你是絕對沒有看到過的,因為它就是為css3而設計的。css3在給css帶來翻天覆地的變化之外,也給sass的@mixin傳遞參數帶來糾結了。一般來說我們的@mixin傳遞的參數是以,
來分隔的,但是css3的一些屬性可以設置多個值,並且多個值以,
分開,如box-shadow:0 0 3px rgba(0,0,0,0.3),inset 0 0 3px rgba(255,255,255,0.3);
這讓@mixin如何給box-shadow傳遞參數啊。所以這種變量後面加...
的變量就出現了。
@mixin box-shadow($shadow...){ -webkit-box-shadow:$shadow; -moz-box-shadow:$shadow; box-shadow:$shadow; }
這樣就完美解決了這個需求了,漂亮吧哈哈。註意這種變量加...
的方式只出現在傳遞參數中,你可以看到上面的大括號裏面的變量都是沒有...
。除了box-shadow,gradient也可以用,反正能使用多個值的屬性裏面都可以用。
變量用#{}
包裹
一般來說,我們設置的變量都是用於屬性值的,而如果用在屬性或者選擇器上,就得以#{}
包裹起來了。
$btnClass: btn !default; $borderDirection: top !default; .#{$btnClass}{ border-#{$borderDirection}:1px solid #ccc; } 解析成的css: .btn{ border-top:1px solid #ccc; }
多個變量一起申明
其實這個還是很實用的,把多個相關的值寫在一個變量裏,然後通過nth($var,index)
來獲取第幾個值。
$linkColor: red blue !default; a{ color:nth($linkColor,1); &:hover{ color:nth($linkColor,2); } } 解析成的css: a { color: red; } a:hover { color: blue; }
關於sass變量揭秘到此為止。如果已經開始使用sass了,歡迎試用sassCore這個庫。
sass揭秘之變量