element-ui
中的樣式文件全部在theme-chalk
文件夾下,其目錄結(jié)果主要包括common
煞赢、fonts
抛计、mixins
和一些組件樣式文件哄孤,組件樣式文件除了日期組件是一個(gè)文件夾外照筑,其它的都是一個(gè)獨(dú)立的.scss
文件。其目錄結(jié)構(gòu)如下所示:
├── README.md
├── gulpfile.js
├── package.json
└── src
├── alert.scss
├── aside.scss
├── autocomplete.scss
├── avatar.scss
├── backtop.scss
├── badge.scss
├── base.scss
├── breadcrumb-item.scss
├── breadcrumb.scss
├── button-group.scss
├── button.scss
├── calendar.scss
├── card.scss
├── carousel-item.scss
├── carousel.scss
├── cascader-panel.scss
├── cascader.scss
├── checkbox-button.scss
├── checkbox-group.scss
├── checkbox.scss
├── col.scss
├── collapse-item.scss
├── collapse.scss
├── color-picker.scss
├── common
│ ├── popup.scss
│ ├── transition.scss
│ └── var.scss
├── container.scss
├── date-picker
│ ├── date-picker.scss
│ ├── date-range-picker.scss
│ ├── date-table.scss
│ ├── month-table.scss
│ ├── picker-panel.scss
│ ├── picker.scss
│ ├── time-picker.scss
│ ├── time-range-picker.scss
│ ├── time-spinner.scss
│ └── year-table.scss
├── date-picker.scss
├── dialog.scss
├── display.scss
├── divider.scss
├── drawer.scss
├── dropdown-item.scss
├── dropdown-menu.scss
├── dropdown.scss
├── fonts
│ ├── element-icons.ttf
│ └── element-icons.woff
├── footer.scss
├── form-item.scss
├── form.scss
├── header.scss
├── icon.scss
├── image.scss
├── index.scss
├── infinite-scroll.scss
├── infiniteScroll.scss
├── input-number.scss
├── input.scss
├── link.scss
├── loading.scss
├── main.scss
├── menu-item-group.scss
├── menu-item.scss
├── menu.scss
├── message-box.scss
├── message.scss
├── mixins
│ ├── _button.scss
│ ├── config.scss
│ ├── function.scss
│ ├── mixins.scss
│ └── utils.scss
├── notification.scss
├── option-group.scss
├── option.scss
├── page-header.scss
├── pagination.scss
├── popconfirm.scss
├── popover.scss
├── popper.scss
├── progress.scss
├── radio-button.scss
├── radio-group.scss
├── radio.scss
├── rate.scss
├── reset.scss
├── row.scss
├── scrollbar.scss
├── select-dropdown.scss
├── select.scss
├── slider.scss
├── spinner.scss
├── step.scss
├── steps.scss
├── submenu.scss
├── switch.scss
├── tab-pane.scss
├── table-column.scss
├── table.scss
├── tabs.scss
├── tag.scss
├── time-picker.scss
├── time-select.scss
├── timeline-item.scss
├── timeline.scss
├── tooltip.scss
├── transfer.scss
├── tree.scss
└── upload.scss
在閱讀element-ui
中的樣式代碼時(shí),需要先了解下scss
和BEM
凝危,下面通過element-ui
中實(shí)際的代碼來介紹下這兩個(gè)技術(shù)點(diǎn)的作用和用途波俄。
1. scss
Sass
是成熟、穩(wěn)定蛾默、強(qiáng)大的CSS預(yù)處理器懦铺,而SCSS
是Sass3
版本當(dāng)中引入的新語法特性,完全兼容CSS3
的同時(shí)繼承了Sass
強(qiáng)大的動(dòng)態(tài)功能支鸡。
1.1 變量
在SCSS
中可以將反復(fù)使用的CSS
樣式定義成一個(gè)變量來引用它冬念,無需寫重復(fù)的CSS
樣式,比如我們可以定義一些常用的顏色牧挣,字體大小急前,邊框等。如element-ui
源碼中瀑构,在common
目錄下有一個(gè)var.scss
文件裆针,定義的全部是一些變量,如果需要修改主題寺晌,只需要修改該文件中的變量值就可以了世吨,大大的提升了代碼的復(fù)用性和可維護(hù)性。以下挑了幾個(gè)很常見的變量呻征,應(yīng)該不陌生耘婚,如下所示:
$--color-primary: #409EFF !default;
/// color|1|Background Color|4
$--color-white: #FFFFFF !default;
/// color|1|Background Color|4
$--color-success: #67C23A !default;
/// color|1|Functional Color|1
$--color-warning: #E6A23C !default;
/// color|1|Functional Color|1
$--color-danger: #F56C6C !default;
/// color|1|Functional Color|1
$--color-info: #909399 !default;
scss
使用$
符號(hào)來標(biāo)識(shí)變量,然后再需要使用的地方直接使用既可。如color:$--color-primary
1.2導(dǎo)入scss文件
在SCSS
文件中需要導(dǎo)入其它文件時(shí)陆赋,直接使用@import
進(jìn)行導(dǎo)入边篮。如下所示:
@import "mixins/mixins";
@import "common/var";
1.3混合器
單獨(dú)的使用變量來定義一些重復(fù)的代碼是遠(yuǎn)遠(yuǎn)不夠的,因?yàn)?strong>變量只能簡單的定義一些顏色奏甫,字體等戈轿,而不能定義重復(fù)的代碼塊,這時(shí)就得需要混合器
來定義代碼塊了阵子∷急混合器使用@mixin
標(biāo)識(shí)符定義,這樣就可以輕易地通過引用這個(gè)名字重用樣式代碼了挠进,如element-ui
源碼中色乾,在mixin
目錄下有一些.scss
文件,定義的全部是一些混合器领突。如在utils.scss
文件中暖璧,有如下一個(gè)混合器,不用設(shè)置顯示成一行的樣式:
@mixin utils-ellipsis {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
定義好后君旦,在需要使用的地方使用include
來引用澎办,如下所示:
&.el-checkbox .el-checkbox__label {
width: 100%;
@include utils-ellipsis;
display: block;
box-sizing: border-box;
padding-left: 24px;
line-height: $--transfer-item-height;
}
混合器并不一定總得生成相同的樣式嘲碱。可以通過在@include
混合器時(shí)給混合器傳參局蚀,來定制混合器生成的精確樣式麦锯。當(dāng)@include
混合器時(shí),參數(shù)其實(shí)就是可以賦值給css
屬性值的變量琅绅,如下所示:
@mixin when($state) {
@at-root {
&.#{$state-prefix + $state} {
@content;
}
}
}
1.4 繼承
使用scss
的時(shí)候扶欣,最后一個(gè)減少重復(fù)的主要特性就是選擇器繼承,選擇器繼承是說一個(gè)選擇器可以繼承為另一個(gè)選擇器定義的所有樣式千扶。這個(gè)通過@extend
語法實(shí)現(xiàn)料祠。如下所示:
@mixin extend-rule($name) {
@extend #{'%shared-'+$name};
}
1.5 @content
在引用混合樣式的時(shí)候,可以先將一段代碼導(dǎo)入到混合指令中澎羞,然后再輸出混合樣式术陶,額外導(dǎo)入的部分將出現(xiàn)在@content
標(biāo)志的地方:
@mixin apply-to-ie6-only {
* html {
@content;
}
}
@include apply-to-ie6-only {
#logo {
background-image: url(/logo.gif);
}
}
編譯后如下所示:
* html #logo {
background-image: url(/logo.gif);
}
關(guān)于@content
的使用,在element-ui
的代碼中隨處可見煤痕,如下所示:
@mixin placeholder {
&::-webkit-input-placeholder {
@content
}
&::-moz-placeholder {
@content
}
&:-ms-input-placeholder {
@content
}
}
2. BEM
BEM
的意思就是塊(block)梧宫、元素(element)、修飾符(modifier)組成摆碉,是由Yandex團(tuán)隊(duì)提出的一種CSS Class
命名方法塘匣,旨在更好的創(chuàng)建CSS/Sass
模塊。BEM
命名具有一定的規(guī)范巷帝,全名規(guī)則為模塊名 + 元素名 + 修飾器名忌卤。如.el-alert--success
。element-ui
源碼中嚴(yán)格遵守了BEM
命名規(guī)范楞泼,并將塊驰徊,元素,修飾符單獨(dú)創(chuàng)建了mixin
堕阔,方便復(fù)用代碼棍厂。
@mixin b($block) {
$B: $namespace+'-'+$block !global;
//通過 #{} 插值語句可以在選擇器或?qū)傩悦惺褂米兞浚? .#{$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;
}
}
}
}
@mixin m($modifier) {
$selector: &;
$currentSelector: "";
@each $unit in $modifier {
$currentSelector: #{$currentSelector + & + $modifier-separator + $unit + ","};
}
@at-root {
#{$currentSelector} {
@content;
}
}
}
2.1 塊
在BEM
命名規(guī)范中,一個(gè)塊可以當(dāng)作一個(gè)組件超陆,在element-ui
中還引入了命名空間牺弹,如alert
組件的命名為:el-alert
。其中el
為命名空間时呀,alert
為組件名张漂。使用命名空間主要是為了防止組件沖突。
2.2 元素
元素是塊的子節(jié)點(diǎn)谨娜,為了表明某個(gè)組件的元素航攒,需要在塊名后面加上__element
,如element-ui
中的alert
組件趴梢,當(dāng)需要在組件上顯示icon
時(shí)漠畜,可以命名為.el-alert__icon
币他,讓人一看就知道是為alert
組件中的icon
定義的樣式。
2.3 修飾符
修飾符是改變某個(gè)塊的外觀的標(biāo)志盆驹。要使用修飾符圆丹,可以將 --modifier
添加到塊中滩愁。如element-ui
中的alert
組件躯喇,可以根據(jù)不同的顏色來表示不同的狀態(tài),有表示成功
硝枉、錯(cuò)誤
廉丽,警告
等不同類型的alert
,不同的類型只需使用不同的樣式既可妻味。如:.el-alert--success
正压,.el-alert--error
等。
3.定義組件樣式
了解完scss
和BEM
后责球,就來了解下element-ui
是如何定義組件樣式的焦履。除了date-picker
組件外,其它組件基本上都是一個(gè)組件對(duì)應(yīng)一個(gè).scss
文件雏逾。這里主要介紹一下alert
組件是如何定義樣式的嘉裤,搞懂了alert
組件后,其它的組件樣式就很容易看懂了栖博,都大同小異屑宠。
3.1 引入公共樣式
首先在文件的最開頭,引入mixins
和var
這兩個(gè)公共樣式仇让。
@import "mixins/mixins";
@import "common/var";
3.2 定義塊級(jí)元素
定義塊級(jí)元素典奉,就是BEM
規(guī)范中的B
,首先來看一下b()
混合器的代碼丧叽,如下所示:
@mixin b($block) {
$B: $namespace+'-'+$block !global;
.#{$B} {
@content;
}
}
該混合器是傳遞一個(gè)block
變量名卫玖,再根據(jù)命名空間來生成一個(gè)變量,然后再使用.#{$B}
來創(chuàng)建一個(gè)class
踊淳,比如傳入一個(gè)alert
骇笔,生成后的類名是這樣子的。
.el-alert{
@content;
}
類型創(chuàng)建好后嚣崭,就需要發(fā)揮@content;
的作用了笨触,就是將相關(guān)的樣式復(fù)制進(jìn)來,如下所示調(diào)用b
的樣式:
@include b(alert) {
width: 100%;
padding: $--alert-padding;
margin: 0;
box-sizing: border-box;
border-radius: $--alert-border-radius;
position: relative;
background-color: $--color-white;
overflow: hidden;
opacity: 1;
display: flex;
align-items: center;
transition: opacity .2s;
}
生成后的代碼如下所示:
.el-alert {
width: 100%;
padding: $--alert-padding;
margin: 0;
box-sizing: border-box;
border-radius: $--alert-border-radius;
position: relative;
background-color: $--color-white;
overflow: hidden;
opacity: 1;
display: flex;
align-items: center;
transition: opacity .2s;
}
3.3 定義子級(jí)元素
定義子級(jí)元素雹舀,就是BEM
規(guī)范中的E
芦劣。e
混合器的代碼如下所示:
@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;
}
}
}
}
這里,需要先搞懂each
和at-root
的用法说榆。
@each
的作用是將$element
中的元素名遍歷出來賦值給$unit
變量虚吟。然后再生成類似el-alert__xx
的class
名稱寸认。
@at-root
指令可以使一個(gè)或多個(gè)規(guī)則被限定輸出在文檔的根層級(jí)上,而不是被嵌套在其父選擇器下串慰。
hitAllSpecialNestRule
用于判斷類型是否為修飾符樣式
偏塞,標(biāo)記樣式
,偽類樣式
中的一種邦鲫。如果是其中的一種灸叼,需要將其嵌套在&
下。如下所示為icon
的樣式庆捺。
@include e(icon) {
font-size: $--alert-icon-size;
width: $--alert-icon-size;
@include when(big) {
font-size: $--alert-icon-large-size;
width: $--alert-icon-large-size;
}
}
3.4 定義修飾符
定義子級(jí)元素古今,就是BEM
規(guī)范中的M
。m
混合器的代碼如下所示:
@mixin m($modifier) {
$selector: &;
$currentSelector: "";
@each $unit in $modifier {
$currentSelector: #{$currentSelector + & + $modifier-separator + $unit + ","};
}
@at-root {
#{$currentSelector} {
@content;
}
}
}
搞懂e
混合器的實(shí)現(xiàn)原理后滔以,看m
混合器的實(shí)現(xiàn)就更簡單了捉腥,就是先遍歷修飾符,然后再生成具有修飾符的class
名你画。alert
中定義的success
類型如下所示:
@include m(success) {
&.is-light {
background-color: $--alert-success-color;
color: $--color-success;
.el-alert__description {
color: $--color-success;
}
}
&.is-dark {
background-color: $--color-success;
color: $--color-white;
}
}
總結(jié)
樣式的定義基本上告一段落了抵碟,主要是活用mixins
中的混合器和BEM
規(guī)范,平時(shí)多寫一些公共樣式基本就能熟練相關(guān)特性了坏匪。