element 源碼學(xué)習(xí)(番外篇) —— SASS五分鐘快速入門

這算是 element 源碼學(xué)習(xí)的番外篇旅急,因為 element 中使用了大量 sass 來寫樣式逢勾。而 UI 框架的核心其實就是樣式。所以坠非,抽空把 sass 學(xué)了一遍,寫了些小 demo 實踐果正,總結(jié)成此文炎码。

SASS 安裝和調(diào)試

簡單說下 sass 如何安裝和編譯調(diào)試。
參照官網(wǎng)秋泳,需要使用 gem 來安裝 sass潦闲。如果是windows用戶沒有 gem 需要先安裝 Ruby

$ gem install sass

如果有權(quán)限問題,需要加上 sudo 迫皱。

$ sudo gem install sass

最后歉闰,通過查詢 sass 版本號驗證是否安裝成功。

$ sass -v

編譯命令很簡單卓起,在項目目錄下編譯選中 .scss和敬、.sass 文件即可。

$ sass hello.scss hello.css

如果是學(xué)習(xí) sass 這一個命令足矣戏阅,其他命令可參考sass 編譯

語法簡述

下面我用自己對 sass 語法的理解昼弟,配合上 demo 快速過一遍 sass 基礎(chǔ)語法。

sass 文件和 scss 文件區(qū)別

兩者其實都是 sass 可以識別的文件奕筐,唯一不同點是 .sass 文件不使用大括號和分號舱痘。如下~

// .scss
$default-color: #FFAACC;
.selected {
    color: $default-color;
}

// .sass
$default-color: #FFAACC
.selected 
    color: $default-color

// .css
.selected {
  color: #FFAACC; 
}

官方文檔推薦使用 .scss 文件類型寫法,避免 .sass 文件的嚴格格式要求報錯离赫。

變量

通過 $ 符號來定義 sass 變量芭逝,變量在樣式內(nèi)外都可定義,用于各個樣式中渊胸。定義的變量不會在編譯后的 CSS 文件中顯示旬盯。

$default-color: #FFAACC;
$border-color: #AAFFCC;
$default-border:  1px solid $border-color;
$extra-color: #BBDD00;

.selected {
    $scoped-width: 60px;
    width: $scoped-width;
    color: $default-color;
    border: $default-border;
}

編譯結(jié)果:

.selected {
  width: 60px;
  color: #FFAACC;
  border: 1px solid #AAFFCC; }

另外注意的一個點是在定義變量時使用的 -_ 的效果是一樣的。即 $border-color$border_color 指向的是同一個變量翎猛。

嵌套

為了避免一些代碼的重復(fù)瓢捉,引入了代碼的嵌套“斐桑看一個例子:

.selected {
    color: #FFAA22;
    h1 {
        color: #FFDD77
    }
    div {
        width: 50px;
        height: 20px;
        span {
            color: #012DD6;
        }
    }
    &:hover {
        color: #FAFAFA;
    }
}

得到的結(jié)果如下:

.selected {
  color: #FFAA22; }
  .selected h1 {
    color: #FFDD77; }
  .selected div {
    width: 50px;
    height: 20px; }
    .selected div span {
      color: #012DD6; }
  .selected:hover {
    color: #FAFAFA; }

從中可以看到泡态,嵌套可以將需要重復(fù)寫選擇器的過程嵌套到一個表達式中了。

父選擇器標(biāo)識符 &

從上面的例子中看到有這么一段 &:hover 而在編譯結(jié)果中得到的結(jié)果是 .selected:hover 迂卢,其實 & 標(biāo)識符就代表了父級選擇器某弦。就這么簡單桐汤,不理解的時候把父級選擇題替換 & 理解下就簡單了。

嵌套css

sass 中的嵌套是可以多個樣式同時嵌套的靶壮。 用法見demo怔毛。

.container .content {
    h1, h2, h3 {margin-bottom: .8em}
}

編譯結(jié)果

.container .content h1, .container .content h2, .container .content h3 {
  margin-bottom: .8em; }

子組合選擇器和同層選擇器

關(guān)于 >+~ 這三個選擇器腾降,是 CSS3 中就有的拣度。在 SASS 中同樣適用。
簡單說下三個選擇器用途(參考 CSS 選擇器):

  • div>p 選取父元素是 <div> 元素的每個 <p> 元素
  • div+p 選擇 <div> 元素之后緊跟的每個 <p> 元素
  • p~ul 選擇前面有 <p> 元素的每個 <ul> 元素螃壤。

看個官網(wǎng)的例子:

article {
    ~ article { border-top: 1px dashed #ccc }
    > section { background: #eee }
    dl > {
      dt { color: #333 }
      dd { color: #555 }
    }
    nav + & { margin-top: 0 }
}

動手編譯出的結(jié)果如下:

article ~ article {
  border-top: 1px dashed #ccc; }
article > section {
  background: #eee; }
article dl > dt {
  color: #333; }
article dl > dd {
  color: #555; }
nav + article {
  margin-top: 0; }

嵌套屬性

屬性嵌套說白了就是把 margin-bottom 這類有 - 符號隔開的屬性拆分開來便于查看和編寫抗果。

nav {
    border: {
    style: solid;
    width: 1px;
    color: #ccc;
    }
  }

這里把 border-style 等屬性進行了拆分,結(jié)果如下:

nav {
  border-style: solid;
  border-width: 1px;
  border-color: #ccc; }

導(dǎo)入

sass 提供了 sass 文件導(dǎo)入功能奸晴≡┝螅可以做一些基礎(chǔ)樣式的復(fù)用。用法很簡單:

// var.scss
$default-color: #AABBCC;

.focused {
    color: red;
    margin: 5px;
}

// h1.scss
h1 {
    color: #BBDDFF;
    margin: 10px;
}

// demo.scss
@import "var01";

$default-color: #FFAADD !default;

.selected {
    color: $default-color;
    @import "h1";
}

以上代碼中將 var.scssh1.scss 兩個文件導(dǎo)入到了 demo.scss 中寄啼,最終生成結(jié)果如下:

.focused {
  color: red;
  margin: 5px; }

.selected {
  color: #AABBCC; }
  .selected h1 {
    color: #BBDDFF;
    margin: 10px; }

從結(jié)果來說說導(dǎo)入的幾個注意點:

  • 導(dǎo)入文件使用 @import 表達式來導(dǎo)入逮光,導(dǎo)入可以是外部導(dǎo)入也可是嵌套導(dǎo)入。上面例子中 var 是外部導(dǎo)入墩划,而 h1 是嵌套導(dǎo)入的涕刚。
  • $default-color: #FFAADD !default; 中的 !default 是定義變量默認值的方式,如果導(dǎo)入文件中有同樣的值優(yōu)先使用導(dǎo)入的值乙帮,如果導(dǎo)入文件中沒有這個值副女,使用默認值。
  • sass 中的 @import 與 css 中的 @import 不同蚣旱,sass 中是編譯的時候就直接導(dǎo)入生成 css 文件了碑幅,而 css 中,只有執(zhí)行到 @import 時塞绿,瀏覽器才會去下載 css 文件沟涨,會導(dǎo)致頁面加載變慢。

靜默注釋

就是在 sass 是否保留注釋內(nèi)容的語法异吻。保留注釋的方式為:在CSS語法允許的地方裹赴,以 /*...*/ 的方式寫注釋就能在生成的 css 文件中看到。再來看一個例子:

// 不顯示
/* 顯示 */

.selected {
    //不顯示
    /* 顯示 */
    color: #FFAADD; // 不顯示
    margin:/* 不顯示 */ 10px; /* 顯示 */
    /* 顯示 */border: 1px dashed /* 不顯示 */ #ccc;
}

// 不顯示
/* 顯示 */

編譯結(jié)果正如注釋所預(yù)測的诀浪。

混合器

混合器在 element 的樣式表中用的非常多棋返,是個很強大的功能±字恚混合器以 @mixin 來導(dǎo)出混合內(nèi)容睛竣,使用 @include 來導(dǎo)入混合內(nèi)容。

基本用法

我的理解是:@mixin 類似定義變量一樣定義個混合器(編譯的時候不顯示 @mixin 的內(nèi)容)求摇,@include 獲取混合器來替換 @include xxxx 的這行內(nèi)容射沟。

// mixin.scss
@mixin rounded-corners {
    -moz-border-radius: 5px;
    -webkit-border-radius: 5px;
    border-radius: 5px;
    div {
        width: 50px;
        height: 20px;
    }
}

.name {
    span {
        color: #FFAADD;
    }
}

// include.scss
@import "mixin";

.notice {
    background-color: green;
    border: 2px solid #00aa00;
    @include rounded-corners;
}

這里在官方 demo 上加了點代碼驗證問題殊者。得到結(jié)果如下:

.name span {
  color: #FFAADD; }

.notice {
  background-color: green;
  border: 2px solid #00aa00;
  -moz-border-radius: 5px;
  -webkit-border-radius: 5px;
  border-radius: 5px; }
  .notice div {
    width: 50px;
    height: 20px; }

這個demo驗證了:1. @mixin 是一個類似變量的內(nèi)容。在 @import 導(dǎo)入的內(nèi)容中只顯示了 .name 樣式验夯。 2. @include 會替換 @include xxx 這段代碼猖吴。就算 @mixin 中有各種寫法都會應(yīng)用到 @include中,如嵌套 CSS挥转。

混合器傳參

混合器可以接收 @include 表達式傳遞的參數(shù)海蔽。而且,參數(shù)可以設(shè)置默認值绑谣。

// mixin.scss
@mixin link-colors($normal: white, $hover: white, $visited: white) {
    color: $normal;
    &:hover { color: $hover; }
    &:visited { color: $visited; }
}

// include.scss
@import "mixin";

// 寫法一党窜,按照默認順序傳遞參數(shù)
a {
    @include link-colors(blue, red, green);
}

// 寫法二,按照參數(shù)名傳遞參數(shù)
b {
    @include link-colors(
      $normal: blue,
      $visited: green,
      $hover: red
  );
}

編譯結(jié)果為:

a {
  color: blue; }
  a:hover {
    color: red; }
  a:visited {
    color: green; }

b {
  color: blue; }
  b:hover {
    color: red; }
  b:visited {
    color: green; }

如果說 @include 中不傳遞參數(shù) @include link-colors(); 域仇,那么生成結(jié)果的 color 都為默認值 white刑然。

element 中的混合

在 element 源碼中用了不少混合寺擂,有一種寫法 sass 的快速入門中沒有提到暇务。就找一個簡單的 el-card 樣式來學(xué)習(xí)下來:

@import "mixins/mixins";
@import "common/var";

@include b(card) {
  border-radius: $--card-border-radius;
  border: 1px solid $--card-border-color;
  background-color: $--color-white;
  overflow: hidden;
  box-shadow: $--box-shadow-light;
  color: $--color-text-primary;

  @include e(header) {
    padding: #{$--card-padding - 2 $--card-padding};
    border-bottom: 1px solid $--card-border-color;
    box-sizing: border-box;
  }

  @include e(body) {
    padding: $--card-padding;
  }
}

從中可以看到所有的屬性都是使用了 @include 方式進行混合的。最終生成的 CSS 文件如下:

.el-card {
  border-radius: 4px;
  border: 1px solid #ebeef5;
  background-color: #fff;
  overflow: hidden;
  box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
  color: #303133; }
  .el-card__header {
    padding: 18px 20px;
    border-bottom: 1px solid #ebeef5;
    box-sizing: border-box; }
  .el-card__body {
    padding: 20px; }

先看下導(dǎo)入怔软,其中 var 文件是項目樣式變量統(tǒng)一保存的地方垦细;mixin 文件用于混合;再加上幾個 @include 表達式挡逼,答案一定是在 mixin 中的括改。我們就直接找到 @mixin b@mixin e 兩個混合項。

@mixin b($block) {
  $B: $namespace+'-'+$block !global; // 定義 B 變量:變量名 el-card

  .#{$B} {
    @content;
  }
}

@mixin e($element) {
  $E: $element !global;
  $selector: &;
  $currentSelector: "";
  @each $unit in $element {
    $currentSelector: #{$currentSelector + "." + $B + $element-separator + $unit + ","};
  }

  @if hitAllSpecialNestRule($selector) {
    @at-root {
      #{$selector} {
        #{$currentSelector} {
          @content;
        }
      }
    }
  } @else {
    @at-root {
      #{$currentSelector} {
        @content;
      }
    }
  }
}

發(fā)現(xiàn)有許多 sass 快速入門中沒有提到過的語法: @if家坎,@else 等等嘱能,這里查閱具體文檔列出其功能:

  • @if @else 這兩者和任何編程語言的 if ... else ... 的用法是一樣的,條件判斷虱疏。if 中條件為 true 進入邏輯惹骂,否則使用 else 邏輯。
  • @at-root @at-root 指令導(dǎo)致一個或多個規(guī)則被限定輸出在文檔的根層級上做瞪,而不是被嵌套在其父選擇器下对粪。
  • @content 樣式內(nèi)容塊可以傳遞到混入(mixin)包含樣式的位置。樣式內(nèi)容塊將出現(xiàn)在混入內(nèi)的任何 @content 指令的位置装蓬。這使得可以定義抽象 關(guān)聯(lián)到選擇器和指令的解析著拭。
  • @each in 類似js用法,遍歷列表獲取每個value值牍帚。
  • #{...}插值語法儡遮,用于在選擇器和屬性名中使用 SassScript 變量,所以 .#{$B} 表達式暗赶,如果 $B 的值為 hello-world峦萎,那么表達式結(jié)果等于 .hello-world

其實看完這些用法屡久,上面的代碼就很好理解了。具體關(guān)于 element 樣式學(xué)習(xí)的細節(jié)將在下篇博客中詳細學(xué)習(xí)爱榔。

繼承

個人感覺繼承就是幾個樣式類寫在一起被环。而且,繼承是可以嵌套的详幽。

.error {
    border: 1px red;
    background-color: #fdd;
}
  
.seriousError {
    @extend .error;
    border-width: 3px;
}

.error02 {
    @extend .seriousError;
    margin: 5px;
}

編譯結(jié)果為:

.error, .seriousError, .error02 {
  border: 1px red;
  background-color: #fdd; }

.seriousError, .error02 {
  border-width: 3px; }

.error02 {
  margin: 5px; }

下面引用下繼承的注意事項:

  • 跟混合器相比筛欢,繼承生成的 css 代碼相對更少。因為繼承僅僅是重復(fù)選擇器唇聘,而不會重復(fù)屬性版姑,所以使用繼承往往比混合器生成的 css 體積更小。如果你非常關(guān)心你站點的速度迟郎,請牢記這一點剥险。
  • 繼承遵從 css 層疊的規(guī)則。當(dāng)兩個不同的 css 規(guī)則應(yīng)用到同一個 html 元素上時宪肖,并且這兩個不同的 css 規(guī)則對同一屬性的修飾存在不同的值表制,css 層疊規(guī)則會決定應(yīng)用哪個樣式。相當(dāng)直觀:通常權(quán)重更高的選擇器勝出控乾,如果權(quán)重相同么介,定義在后邊的規(guī)則勝出。

所以蜕衡,其實繼承相比混合更簡單壤短。繼承只是選擇器的重復(fù),而混合是用一段代碼替換標(biāo)簽 @include 標(biāo)簽慨仿。

最后

由于 element 項目中使用了大量的 sass 樣式久脯,所以想了解 element 必須對 sass 有一定了解。本文簡單解決了 sass 是什么镰吆?基礎(chǔ)用法怎么用帘撰?兩個問題。更加深入的 sass 語法涉及的不多鼎姊,算是快速入門博客啦骡和。
在了解了 sass,能夠看懂 element 中的樣式表后相寇,就可以愉快的去學(xué)習(xí) element 源碼啦~

打個廣告

上海鏈家-鏈家上海研發(fā)中心需求大量前端慰于、后端、測試唤衫,需要內(nèi)推請將簡歷發(fā)送至 dingxiaojie001@ke.com婆赠。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子休里,更是在濱河造成了極大的恐慌蛆挫,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,042評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件妙黍,死亡現(xiàn)場離奇詭異悴侵,居然都是意外死亡,警方通過查閱死者的電腦和手機拭嫁,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,996評論 2 384
  • 文/潘曉璐 我一進店門可免,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人做粤,你說我怎么就攤上這事浇借。” “怎么了怕品?”我有些...
    開封第一講書人閱讀 156,674評論 0 345
  • 文/不壞的土叔 我叫張陵妇垢,是天一觀的道長。 經(jīng)常有香客問我肉康,道長闯估,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,340評論 1 283
  • 正文 為了忘掉前任迎罗,我火速辦了婚禮睬愤,結(jié)果婚禮上片仿,老公的妹妹穿的比我還像新娘纹安。我一直安慰自己,他們只是感情好砂豌,可當(dāng)我...
    茶點故事閱讀 65,404評論 5 384
  • 文/花漫 我一把揭開白布厢岂。 她就那樣靜靜地躺著,像睡著了一般阳距。 火紅的嫁衣襯著肌膚如雪塔粒。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,749評論 1 289
  • 那天筐摘,我揣著相機與錄音卒茬,去河邊找鬼。 笑死咖熟,一個胖子當(dāng)著我的面吹牛圃酵,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播馍管,決...
    沈念sama閱讀 38,902評論 3 405
  • 文/蒼蘭香墨 我猛地睜開眼郭赐,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了确沸?” 一聲冷哼從身側(cè)響起捌锭,我...
    開封第一講書人閱讀 37,662評論 0 266
  • 序言:老撾萬榮一對情侶失蹤俘陷,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后观谦,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體拉盾,經(jīng)...
    沈念sama閱讀 44,110評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,451評論 2 325
  • 正文 我和宋清朗相戀三年豁状,在試婚紗的時候發(fā)現(xiàn)自己被綠了盾剩。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,577評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡替蔬,死狀恐怖告私,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情承桥,我是刑警寧澤驻粟,帶...
    沈念sama閱讀 34,258評論 4 328
  • 正文 年R本政府宣布,位于F島的核電站凶异,受9級特大地震影響蜀撑,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜剩彬,卻給世界環(huán)境...
    茶點故事閱讀 39,848評論 3 312
  • 文/蒙蒙 一酷麦、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧喉恋,春花似錦沃饶、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,726評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至氓鄙,卻和暖如春馆揉,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背抖拦。 一陣腳步聲響...
    開封第一講書人閱讀 31,952評論 1 264
  • 我被黑心中介騙來泰國打工升酣, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人态罪。 一個月前我還...
    沈念sama閱讀 46,271評論 2 360
  • 正文 我出身青樓噩茄,卻偏偏與公主長得像,于是被迫代替她去往敵國和親向臀。 傳聞我的和親對象是個殘疾皇子巢墅,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,452評論 2 348