1. 程式人生 > >element 原始碼學習(番外篇) —— SASS五分鐘快速入門

element 原始碼學習(番外篇) —— SASS五分鐘快速入門

這算是 element 原始碼學習的番外篇,因為 element 中使用了大量 sass 來寫樣式。而 UI 框架的核心其實就是樣式。所以,抽空把 sass 學了一遍,寫了些小 demo 實踐,總結成此文。

SASS 安裝和除錯

簡單說下 sass 如何安裝和編譯除錯。
參照官網,需要使用 gem 來安裝 sass。如果是windows使用者沒有 gem 需要先安裝 Ruby

$ gem install sass

如果有許可權問題,需要加上 sudo

$ sudo gem install sass

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

$ 
sass -v

編譯命令很簡單,在專案目錄下編譯選中 .scss.sass 檔案即可。

$ sass hello.scss hello.css

如果是學習 sass 這一個命令足矣,其他命令可參考sass 編譯

語法簡述

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

sass 檔案和 scss 檔案區別

兩者其實都是 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 變數,變數在樣式內外都可定義,用於各個樣式中。定義的變數不會在編譯後的 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; }

編譯結果:

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

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

巢狀

為了避免一些程式碼的重複,引入了程式碼的巢狀。看一個例子:

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

得到的結果如下:

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

從中可以看到,巢狀可以將需要重複寫選擇器的過程巢狀到一個表示式中了。

父選擇器識別符號 &

從上面的例子中看到有這麼一段 &:hover 而在編譯結果中得到的結果是 .selected:hover ,其實 & 識別符號就代表了父級選擇器。就這麼簡單,不理解的時候把父級選擇題替換 & 理解下就簡單了。

巢狀css

sass 中的巢狀是可以多個樣式同時巢狀的。 用法見demo。

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

編譯結果

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

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

關於 >+~ 這三個選擇器,是 CSS3 中就有的。在 SASS 中同樣適用。
簡單說下三個選擇器用途(參考 CSS 選擇器):

  • div>p 選取父元素是 元素的每個

    元素

  • div+p 選擇 元素之後緊跟的每個

    元素

  • p~ul 選擇前面有

    元素的每個

      元素。

看個官網的例子:

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

動手編譯出的結果如下:

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 等屬性進行了拆分,結果如下:

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

匯入

sass 提供了 sass 檔案匯入功能。可以做一些基礎樣式的複用。用法很簡單:

// 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 兩個檔案匯入到了 demo.scss 中,最終生成結果如下:

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

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

從結果來說說匯入的幾個注意點:

  • 匯入檔案使用 @import 表示式來匯入,匯入可以是外部匯入也可是巢狀匯入。上面例子中 var 是外部匯入,而 h1 是巢狀匯入的。
  • $default-color: #FFAADD !default; 中的 !default 是定義變數預設值的方式,如果匯入檔案中有同樣的值優先使用匯入的值,如果匯入檔案中沒有這個值,使用預設值。
  • sass 中的 @import 與 css 中的 @import 不同,sass 中是編譯的時候就直接匯入生成 css 檔案了,而 css 中,只有執行到 @import 時,瀏覽器才會去下載 css 檔案,會導致頁面載入變慢。

靜默註釋

就是在 sass 是否保留註釋內容的語法。保留註釋的方式為:在CSS語法允許的地方,以 /*...*/ 的方式寫註釋就能在生成的 css 檔案中看到。再來看一個例子:

// 不顯示
/* 顯示 */

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

// 不顯示
/* 顯示 */

編譯結果正如註釋所預測的。

混合器

混合器在 element 的樣式表中用的非常多,是個很強大的功能。混合器以 @mixin 來匯出混合內容,使用 @include 來匯入混合內容。

基本用法

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

// 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 上加了點程式碼驗證問題。得到結果如下:

.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 是一個類似變數的內容。在 @import 匯入的內容中只顯示了 .name 樣式。 2. @include 會替換 @include xxx 這段程式碼。就算 @mixin 中有各種寫法都會應用到 @include中,如巢狀 CSS。

混合器傳參

混合器可以接收 @include 表示式傳遞的引數。而且,引數可以設定預設值。

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

// include.scss
@import "mixin";

// 寫法一,按照預設順序傳遞引數
a {
    @include link-colors(blue, red, green);
}

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

編譯結果為:

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

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

如果說 @include 中不傳遞引數 @include link-colors(); ,那麼生成結果的 color 都為預設值 white。

element 中的混合

在 element 原始碼中用了不少混合,有一種寫法 sass 的快速入門中沒有提到。就找一個簡單的 el-card 樣式來學習下來:

@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; }

先看下匯入,其中 var 檔案是專案樣式變數統一儲存的地方;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;
      }
    }
  }
}

發現有許多 sass 快速入門中沒有提到過的語法: @if@else 等等,這裡查閱具體文件列出其功能:

  • @if @else 這兩者和任何程式語言的 if … else … 的用法是一樣的,條件判斷。if 中條件為 true 進入邏輯,否則使用 else 邏輯。
  • @at-root @at-root 指令導致一個或多個規則被限定輸出在文件的根層級上,而不是被巢狀在其父選擇器下。
  • @content 樣式內容塊可以傳遞到混入(mixin)包含樣式的位置。樣式內容塊將出現在混入內的任何 @content 指令的位置。這使得可以定義抽象 關聯到選擇器和指令的解析。
  • @each in 類似js用法,遍歷列表獲取每個value值。
  • #{...}插值語法,用於在選擇器和屬性名中使用 SassScript 變數,所以 .#{$B} 表示式,如果 $B 的值為 hello-world,那麼表示式結果等於 .hello-world

其實看完這些用法,上面的程式碼就很好理解了。具體關於 element 樣式學習的細節將在下篇部落格中詳細學習。

繼承

個人感覺繼承就是幾個樣式類寫在一起。而且,繼承是可以巢狀的。

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

.seriousError {
    @extend .error;
    border-width: 3px;
}

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

編譯結果為:

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

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

.error02 {
  margin: 5px; }

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

  • 跟混合器相比,繼承生成的 css 程式碼相對更少。因為繼承僅僅是重複選擇器,而不會重複屬性,所以使用繼承往往比混合器生成的 css 體積更小。如果你非常關心你站點的速度,請牢記這一點。
  • 繼承遵從 css 層疊的規則。當兩個不同的 css 規則應用到同一個 html 元素上時,並且這兩個不同的 css 規則對同一屬性的修飾存在不同的值,css 層疊規則會決定應用哪個樣式。相當直觀:通常權重更高的選擇器勝出,如果權重相同,定義在後邊的規則勝出。

所以,其實繼承相比混合更簡單。繼承只是選擇器的重複,而混合是用一段程式碼替換標籤 @include 標籤。

最後

由於 element 專案中使用了大量的 sass 樣式,所以想了解 element 必須對 sass 有一定了解。本文簡單解決了 sass 是什麼?基礎用法怎麼用?兩個問題。更加深入的 sass 語法涉及的不多,算是快速入門部落格啦。
在瞭解了 sass,能夠看懂 element 中的樣式表後,就可以愉快的去學習 element 原始碼啦~

相關推薦

element 原始碼學習 —— SASS分鐘快速入門

這算是 element 原始碼學習的番外篇,因為 element 中使用了大量 sass 來寫樣式。而 UI 框架的核心其實就是樣式。所以,抽空把 sass 學了一遍,寫了些小 demo 實踐,總結成此文。 SASS 安裝和除錯 簡單說下 sas

Netty學習筆記 - ChannelHandler、ChannelPipeline和ChannelHandlerContext的聯絡

> 這一篇是 [ChannelHandler 和 ChannelPipeline](https://www.cnblogs.com/niklai/p/12951811.html) 的番外篇,主要從原始碼的角度來學習 ChannelHandler、ChannelHandler 和 ChannelPipel

前端基於react,後端基於.net core2.0的開發之路 後端使用T4模板,生成某些類

bsp 。。 bubuko 按鈕 uil out eva 下載地址 所有 1.介紹 因為開發過程中,有部分類是你加一個模型,就需要去改動的,每次加非常的煩,或者有些類,你只用到了他基類的方法,但是你還必須建一個文件才能調用他基類的方法,也很煩。 這個時候,T4就非常有用了。

】ASP.NET MVC快速入門之免費jQuery控件庫MVC5+EF6

south ade 批量刪除 HP 存儲 重新 mode eve 穩定 目錄 【第一篇】ASP.NET MVC快速入門之數據庫操作(MVC5+EF6) 【第二篇】ASP.NET MVC快速入門之數據註解(MVC5+EF6) 【第三篇】ASP.NET MVC快速入門之安全策略

實力封裝:Unity打包AssetBundle

再次 tar 我們 var ext 番外篇 菜單 fontsize 處女座 前情提要:第二種打包方式。 自定義AssetBundle包擴展名 在之前的教程中,我們已經多次提到過擴展名了,並且也已經說明了如何設置自定義的AssetBundle擴展名。至於為什麽還要把它單獨拿出

ASP.NET Aries 高級開發教程:Excel導入之代碼編寫

chan 導入 設置 jna 配置 決定 ptc UNC 番外篇 前言: 以許框架提供的導入配置功能,已經能解決95%以上的導入情況,但有些情況總歸還是得代碼來解決。 本篇介紹與導入相關的代碼。 1、前端追加導入時Post的參數: var grid = new

『中級』docker之wordpress容器SSL78

block load 進行 fault lib tro docker lin system >原創文章,歡迎轉載。轉載請註明:轉載自IT人故事會,謝謝!>原文鏈接地址:『中級篇』docker之wordpress容器SSL(番外篇)(78) 搞了2天終於搞定了,現

『中級』docker之java容器執行接springboot-jar79

學了docker這麼久終於開始實戰了,所有部署方式全部使用docker的方式感覺特別爽,我這裡分享下,我部署springboot的富jar包。 下載java的映象 docker pull java:openjdk-8 spring boot 打包後的富jar 放入指定的目錄。

『中級』docker之java容器運行置springboot-jar79

可選 執行 class doc 全部 -a Language -bash ans 學了docker這麽久終於開始實戰了,所有部署方式全部使用docker的方式感覺特別爽,我這裏分享下,我部署springboot的富jar包。 下載java的鏡像 docker pull j

『中級』docker之執行nginx跳轉到本地的jar並配置https80

>原創文章,歡迎轉載。轉載請註明:轉載自IT人故事會,謝謝!>原文連結地址:『中級篇』docker之執行nginx跳轉到本地的jar並配置https(番外篇)(80) 真實的環境,一個1核2g記憶體,安裝了mysql容器,java容器,nginx容器。具體安裝docker我就不說了,沒啥

『中級』docker之運行nginx跳轉到本地的jar並配置https80

ide 內部 鏈接 class and format 環境 keepaliv file >原創文章,歡迎轉載。轉載請註明:轉載自IT人故事會,謝謝!>原文鏈接地址:『中級篇』docker之運行nginx跳轉到本地的jar並配置https(番外篇)(80) 真實的

[uboot] uboot串列埠&console&stdio裝置工作流程

轉自 https://blog.csdn.net/ooonebook/article/details/53313112   一、uboot serial框架 1、serial模組驅動模型 在《[uboot] (番外篇)uboot 驅動模型》中我們已經介紹uboot的驅

[SLAM]:一起做RGB-D SLAM(5)

    本文轉自高翔老師的部落格,建議在學完教程的第二講後,插入學習,做到工程快速入門。     原文連結:https://www.cnblogs.com/gaoxiang12/p/4719156.html  Visual Odometr

[SLAM]:一起做RGB-D SLAM(4)

    本文轉自高翔老師的部落格,建議在學完教程的第二講後,插入學習,做到工程快速入門。     原文連結:https://www.cnblogs.com/gaoxiang12/p/4669490.html 上講回顧   上一講中,我們理解了如

[SLAM]:一起做RGB-D SLAM(3)

    本文轉自高翔老師的部落格,建議在學完教程的第二講後,插入學習,做到工程快速入門。     原文連結:https://www.cnblogs.com/gaoxiang12/p/4659805.html      

[SLAM]:一起做RGB-D SLAM(7)

    本文轉自高翔老師的部落格,建議在學完教程的第二講後,插入學習,做到工程快速入門。     原文連結:https://www.cnblogs.com/gaoxiang12/p/4754948.html 添加回環檢測 簡單迴環檢測的流程

[SLAM]:一起做RGB-D SLAM(6)

    本文轉自高翔老師的部落格,建議在學完教程的第二講後,插入學習,做到工程快速入門。     原文連結:https://www.cnblogs.com/gaoxiang12/p/4739934.html 圖優化工具g2o的入門   在上一講

[uboot] uboot 驅動模型

建議先看《[uboot] (番外篇)uboot之fdt介紹》,瞭解一下uboot的fdt的功能,在驅動模型中會使用到。 =========================================================================

[uboot] uboot之fdt介紹

以下例子都以project X專案tiny210(s5pv210平臺,armv7架構)為例 建議先看《[[uboot] (番外篇)uboot relocation介紹》和《[uboot] (第四章)uboot流程——uboot編譯流程》 =============

『中級』docker之虛擬機器建立vagrant技巧81

原創文章,歡迎轉載。轉載請註明:轉載自IT人故事會,謝謝! 原文連結地址:『中級篇』docker之虛擬機器建立vagrant技巧(番外篇)(81) 之前一直用的原生的centos7的源映象安裝虛擬機器,然後在這個基礎執行shell指令碼,經常出