Element 2 組件源碼剖析之Icon圖標

這是我參與8月更文挑戰的第5天,活動詳情查看:8月更文挑戰javascript

0x00 簡介

本文將深刻分析組件 Icon 源碼,剖析其實現原理,耐心讀完,相信會對您有所幫助。 組件文檔 Iconcss

packages/icon/src/icon.vue 文件是組件源碼實現。 github源碼 icon.vuehtml

0x01 組件源碼

組件 Icon 的源碼應是最簡單的。封裝了字體圖標的使用方法。提供了屬性 name,用於指定使用的圖標名稱。vue

<template>
  <i :class="'el-icon-' + name"></i>
</template>

<script> export default { name: 'ElIcon', props: { name: String } }; </script>
複製代碼

組件使用 <el-icon name="iconName"></el-icon> 等同於 <i class="el-icon-iconName"></i>,因此使用圖標功能有兩種實現方式。官方更推薦後者也就是直接使用字體圖標。java

Icon組件示例中直接使用了後者,沒有調用el-icon組件 。node

<i class="el-icon-edit"></i> 
<i class="el-icon-share"></i> 
<i class="el-icon-delete"></i>
複製代碼

支持圖標功能的其餘組件內部實現大多使用字體圖標方式,而不是調用el-icon組件,下面以圖標按鈕爲例。git

// 圖標按鈕 使用方式
<el-button type="primary" icon="el-icon-search">搜索</el-button>

// button 源碼 packages\button\src\button.vue
<template> <button class="el-button" > ... <i class="el-icon-loading" v-if="loading"></i> <i :class="icon" v-if="icon && !loading"></i> ... </button> </template>
複製代碼

0x02 字體圖標樣式

📁 src\fonts

用於存放字體圖標使用字體文件。github

element-icons.ttfTrueType格式的字體文件。 Windows和Mac上常見的字體格式,是一種原始格式,所以它並無爲網頁進行優化處理。
element-icons.woffWeb Open Font 的字體文件是一個開放的TrueType/OpenType的壓縮版,同時支持元數據包的分離。 Web字體中最佳格式,針對網頁進行特殊優化web

📃 src\icon.scss

@font-face 自定義字體庫

組件樣式源碼 packages\theme-chalk\src\icon.scss 首先自定義圖標字體庫。chrome

// CSS @規則 指定自定義字體
@font-face { 
  font-family: "element-icons";
  src: url("#{$--font-path}/element-icons.woff") format("woff"),/* chrome, firefox */
       url("#{$--font-path}/element-icons.ttf") format("truetype"); /* chrome, firefox, opera, Safari, Android, iOS 4.2+*/
  font-weight: normal;
  font-display: $--font-display;
  font-style: normal;
}
複製代碼
  • font-family: 指定自定義字庫名稱爲 element-icons
  • src:設置字體的加載路徑和格式 [ <url> [ format( <string> ) ],經過逗號分隔多個加載路徑和格式。
  • [ <url> [ format( <string> ) ]url指定自定義的字體的存放路徑 ;string指定自定義的字體的格式,主要用來幫助瀏覽器識別。 變量$--font-path值爲 fonts
  • font-weight: 定義字體的粗細。 normal 默認值定義標準的字符。
  • font-style: 定義字體樣式使用斜體、傾斜或正常字體。 normal 默認值正常字體。
  • font-display:決定了一個@font-face 在不一樣的下載時間和可用時間下是如何展現的。變量 $--font-display 值爲auto,字體顯示策略由用戶代理定義。

el-icon-element 樣式

經過CSS選擇器,對classel-icon-開始 或者 包含 el-icon-的元素設置樣式。經過font-family引用自定義字體font-family: element-icons !important;

[class*=" el-icon-"],
[class^="el-icon-"] {
  font-family: element-icons !important;
  // ...
}

// ...

// margin 左右設置
.el-icon--right {
  margin-left: 5px;
}
.el-icon--left {
  margin-right: 5px;
} 
複製代碼

el-icon-iconName:before 圖標設置

顯示圖標使用 CSS 僞元素選擇器::before進行添加,自身的content屬性是對應的圖標代碼。 ::before 匹配一個虛擬元素,主要被用於爲當前元素增長裝飾性內容的。顯示的內容是其自身的content屬性,默認是內聯元素。

// 圖標內容設置
.el-icon-iconName:before {
  content: "\eXXX";
}

// ...
複製代碼

前文講到腳本 build/bin/iconInit.js ,解析 packages/theme-chalk/src/icon.scss,提取全部 icon 名字生成 examples/icon.json 圖標集合文件。

// build\bin\iconInit.js
// 遍歷 nodes
nodes.forEach((node) => {
  // ...
  // node獲取選擇器名稱匹配 .el-icon-iconName:before 
  var reg = new RegExp(/\.el-icon-([^:]+):before/);
  // ...
});
複製代碼

icon.json 在官網入口文件examples\entry.js 中導入,掛載到 Vue.prototype。 用於Icon圖標文檔頁生成全部的圖標集合 。

image.png

loding 旋轉實現

使用 css animation 實現 loading 圖標不停旋轉效果。

.el-icon-loading {
  animation: rotating 2s linear infinite;
} 

@keyframes rotating {
  0% {
    transform: rotateZ(0deg);
  }
  100% {
    transform: rotateZ(360deg);
  }
} 
複製代碼

📃 lib\icon.scss

前文可知使用 gulpfile.js編譯 scss 文件轉換爲CSS,通過瀏覽器兼容、格式壓縮,最後生成 packages\theme-chalk\lib\icon.css

image.png

0x04 原理圖解

一圖描述下使用圖標時,發生了什麼。

<i class="el-icon-share"></i>
// 或
<el-icon name="share"></el-icon>  
複製代碼

image.png

0x05 📚參考

"@font-face",MDN
"::before",MDN
"CSS selectors",W3C

相關文章
相關標籤/搜索