sass揭祕之變量

全局變量和局部變量

要了解sass或less的變量,有必要先了解下js的變量定義,先來一段js的代碼:php

var a = 1;
(function(){
    a = 5;
})();
console.log(a);//5

 

上面這段代碼,匿名函數裏面的a由於沒有使用var關鍵字來定義,因此當咱們在函數外打印a的時候,獲得的是5,改變了一開始定義的1css

var a = 1;
(function(){
    var a = 5;
})();
console.log(a);//1

 

而這段代碼,匿名函數裏面的a使用了var關鍵字來定義,因此當咱們在函數外打印a的時候,獲得的是1,一開始定義的值。java

若是你明白了上面兩個的區別,那下面就好辦了,若是你尚未明白,那麼建議先去看下js的變量申明。 也許你如今已經看出眉目了,其實sass的變量設計用的是上面兩段代碼中的第一段思想,即在局部不使用var來申明,而less用的是第二段思想,即局部使用var來申明,這就是不少人所說的爲何sass沒有局部變量。咱們來兩段代碼測試下:css3

sass版git

$color:red;
p{
    $color:blue;
    color:$color;//blue
}
a{
    color:$color;//blue
}

 

less版github

@color:red;
p{
    @color:blue;
    color:@color;//blue
}
a{
    color:@color;//red
}

 

簡單總結下:若是全局申明瞭一個變量a,sass中若是使用到局部中是屬於改變a的值,因此後來全部的都是改變以後的值;而less中使用到局部變量則屬於在局部從新定義a的值,不影響其餘地方。說到底,其實sass和less的變量其實都是js變量的表現形式,二者都有其科學性,只是設計思路不一樣而已。web

固然說到這裏,可能有人會說了,那sass就沒有局部變量嘍。其實否則,正確的說法應該是:在有全局變量的狀況下,sass是沒有局部變量的。意思是若是要看到sass的局部變量,請不要設置全局變量。代碼爲證:sass

p{
    $color:blue;
    color:$color;//blue
}
a{
    color:$color;//$color未定義
}

 

這是一個沒有定義全局變量$color的例子,上面的p元素的color爲blue,而a裏面就會報錯由於$color沒定義,它沒有獲取到p元素裏面定義的那個$color變量,這證實了其實sass一樣存在局部變量,只是這個前提是得沒有全局變量。less

相信到這裏,你們應該對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這個庫。

相關文章
相關標籤/搜索