这是我参与8月更文挑战的第5天,活动详情查看:8月更文挑战javascript
本文将深刻分析组件 Icon
源码,剖析其实现原理,耐心读完,相信会对您有所帮助。 组件文档 Iconcss
packages/icon/src/icon.vue
文件是组件源码实现。 github源码 icon.vuehtml
组件 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>
复制代码
用于存放字体图标使用字体文件。github
element-icons.ttf
是 TrueType格式的字体文件。 Windows和Mac上常见的字体格式,是一种原始格式,所以它并无为网页进行优化处理。
element-icons.woff
是 Web Open Font 的字体文件是一个开放的TrueType/OpenType的压缩版,同时支持元数据包的分离。 Web字体中最佳格式,针对网页进行特殊优化。web
组件样式源码 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
,字体显示策略由用户代理定义。经过CSS选择器,对class
以el-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;
}
复制代码
显示图标使用 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图标
文档页生成全部的图标集合 。
使用 css animation 实现 loading
图标不停旋转效果。
.el-icon-loading {
animation: rotating 2s linear infinite;
}
@keyframes rotating {
0% {
transform: rotateZ(0deg);
}
100% {
transform: rotateZ(360deg);
}
}
复制代码
前文可知使用 gulpfile.js
编译 scss
文件转换为CSS
,通过浏览器兼容、格式压缩,最后生成 packages\theme-chalk\lib\icon.css
。
一图描述下使用图标时,发生了什么。
<i class="el-icon-share"></i>
// 或
<el-icon name="share"></el-icon>
复制代码