1. 程式人生 > >sass揭秘之變量

sass揭秘之變量

box 幫我 keyword str 區別 除了 形式 選擇 試用

全局變量和局部變量

要了解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揭秘之變量