element-ui源碼閱讀-樣式

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í),需要先了解下scssBEM凝危,下面通過element-ui中實(shí)際的代碼來介紹下這兩個(gè)技術(shù)點(diǎn)的作用和用途波俄。

1. scss

Sass是成熟、穩(wěn)定蛾默、強(qiáng)大的CSS預(yù)處理器懦铺,而SCSSSass3版本當(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--successelement-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.定義組件樣式

了解完scssBEM后责球,就來了解下element-ui是如何定義組件樣式的焦履。除了date-picker組件外,其它組件基本上都是一個(gè)組件對(duì)應(yīng)一個(gè).scss文件雏逾。這里主要介紹一下alert組件是如何定義樣式的嘉裤,搞懂了alert組件后,其它的組件樣式就很容易看懂了栖博,都大同小異屑宠。

3.1 引入公共樣式

首先在文件的最開頭,引入mixinsvar這兩個(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;
      }
    }
  }
}

這里,需要先搞懂eachat-root的用法说榆。

@each的作用是將$element中的元素名遍歷出來賦值給$unit變量虚吟。然后再生成類似el-alert__xxclass名稱寸认。

@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ī)范中的Mm混合器的代碼如下所示:

@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)特性了坏匪。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末拟逮,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子剥槐,更是在濱河造成了極大的恐慌唱歧,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,755評(píng)論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件粒竖,死亡現(xiàn)場離奇詭異颅崩,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)蕊苗,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,305評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門沿后,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人朽砰,你說我怎么就攤上這事尖滚。” “怎么了瞧柔?”我有些...
    開封第一講書人閱讀 165,138評(píng)論 0 355
  • 文/不壞的土叔 我叫張陵漆弄,是天一觀的道長。 經(jīng)常有香客問我造锅,道長撼唾,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,791評(píng)論 1 295
  • 正文 為了忘掉前任哥蔚,我火速辦了婚禮倒谷,結(jié)果婚禮上蛛蒙,老公的妹妹穿的比我還像新娘。我一直安慰自己渤愁,他們只是感情好牵祟,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,794評(píng)論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著抖格,像睡著了一般诺苹。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上他挎,一...
    開封第一講書人閱讀 51,631評(píng)論 1 305
  • 那天筝尾,我揣著相機(jī)與錄音捡需,去河邊找鬼办桨。 笑死,一個(gè)胖子當(dāng)著我的面吹牛站辉,可吹牛的內(nèi)容都是我干的呢撞。 我是一名探鬼主播,決...
    沈念sama閱讀 40,362評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼饰剥,長吁一口氣:“原來是場噩夢(mèng)啊……” “哼殊霞!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起汰蓉,我...
    開封第一講書人閱讀 39,264評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤绷蹲,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后顾孽,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體祝钢,經(jīng)...
    沈念sama閱讀 45,724評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,900評(píng)論 3 336
  • 正文 我和宋清朗相戀三年若厚,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了拦英。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,040評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡测秸,死狀恐怖疤估,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情霎冯,我是刑警寧澤铃拇,帶...
    沈念sama閱讀 35,742評(píng)論 5 346
  • 正文 年R本政府宣布,位于F島的核電站沈撞,受9級(jí)特大地震影響慷荔,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜关串,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,364評(píng)論 3 330
  • 文/蒙蒙 一拧廊、第九天 我趴在偏房一處隱蔽的房頂上張望监徘。 院中可真熱鬧,春花似錦吧碾、人聲如沸凰盔。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,944評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽户敬。三九已至,卻和暖如春睁本,著一層夾襖步出監(jiān)牢的瞬間尿庐,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,060評(píng)論 1 270
  • 我被黑心中介騙來泰國打工呢堰, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留抄瑟,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,247評(píng)論 3 371
  • 正文 我出身青樓枉疼,卻偏偏與公主長得像皮假,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子骂维,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,979評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容