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;
}
官方文件推薦使用 .scs
s 檔案型別寫法,避免 .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.scss
和 h1.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容器SSL(番外篇)(78)
block load 進行 fault lib tro docker lin system >原創文章,歡迎轉載。轉載請註明:轉載自IT人故事會,謝謝!>原文鏈接地址:『中級篇』docker之wordpress容器SSL(番外篇)(78) 搞了2天終於搞定了,現
『中級篇』docker之java容器執行外接springboot-jar(番外篇)(79)
學了docker這麼久終於開始實戰了,所有部署方式全部使用docker的方式感覺特別爽,我這裡分享下,我部署springboot的富jar包。 下載java的映象 docker pull java:openjdk-8 spring boot 打包後的富jar 放入指定的目錄。
『中級篇』docker之java容器運行外置springboot-jar(番外篇)(79)
可選 執行 class doc 全部 -a Language -bash ans 學了docker這麽久終於開始實戰了,所有部署方式全部使用docker的方式感覺特別爽,我這裏分享下,我部署springboot的富jar包。 下載java的鏡像 docker pull j
『中級篇』docker之執行nginx跳轉到本地的jar並配置https(番外篇)(80)
>原創文章,歡迎轉載。轉載請註明:轉載自IT人故事會,謝謝!>原文連結地址:『中級篇』docker之執行nginx跳轉到本地的jar並配置https(番外篇)(80) 真實的環境,一個1核2g記憶體,安裝了mysql容器,java容器,nginx容器。具體安裝docker我就不說了,沒啥
『中級篇』docker之運行nginx跳轉到本地的jar並配置https(番外篇)(80)
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指令碼,經常出