前言
最近,在 BuildAdmin 项目的开发中,我们规划了一个 Icon
组件,我们希望通过这个组件,能直接同时使用多种图标库的图标(一种语法,实现无限的图标扩展和高度兼容性)并且,实现该 Icon
之后,理应还有一个图标选择器
,可以加载出不同图标库的所有可用图标,方便直接选择使用,文末提供完整代码。
由于项目是基于
Vite
的,所以本文会出现少量只在Vite
下才能运行的代码(vite专有api等)。
我们的Icon
和Icon选择器
组件,实现了以下常用图标库的支持,如果还有其它你喜欢的图标库,可以参考我们的实现方式,自行加上即可。
- 本地SVG图标:直接将svg文件放入指定的文件夹内,实现自动加载该文件夹所有的svg,并利用
Icon
组件直接使用,无需手动import
。 - ElementPlus的icon,首先使用官方提供的方法全局注册,然后和
Icon
组件整合,实现语法的兼容性。 - Iconfont(阿里巴巴矢量图标库),实现了自动载入
Font clas
(css链接,载入后即可通过class来使用对应的字体图标),实现Icon
组件的语法兼容性,然后自动解析出Font class内的所有图标名称,以供图标选择器使用。 - FontAwesome,这是一款很常用的图标库,包含了675个图标,
Icon
组件实现了自动加载,语法兼容;并且自动解析所有图标名称,以供图标选择器使用。
使用四种图标的语法
<!-- 本地图标 -->
<Icon name="local-图标文件名" size="18px" color="#000000" />
<!-- Element Plus图标 -->
<Icon name="el-icon-图标名" size="18px" color="#000000" />
<!-- FontAwesome图标 -->
<Icon name="fa fa-图标名" size="18px" color="#000000" />
<!-- Iconfont图标 -->
<Icon name="iconfont 图标名" size="18px" color="#000000" />
具体实现
目录结构
BuildAdmin
├─src
│ │ App.vue
│ │ main.ts
| | vite.config.ts
│ ├─assets
│ │ └─icons 存放本地SVG文件的文件夹
│ ├─components
│ │ ├─icon
│ │ ├─svg
│ │ │ ├─index.ts 加载本地SVG文件的实现
│ │ │ ├─index.vue svg显示组件的实现
│ │ ├─index.vue Icon 组件的实现
│ │ └─selector.vue 图标选择器组件的的实现
| ├─utils
│ │ └─common.ts公共辅助函数库
本地SVG
我们准备了一个目录/src/assets/icons
,将svg文件放入其中,实现自动加载全部文件(不依赖第三方包),并直接以:<Icon name="local-图标文件名" />
的语法使用图标。
第一步:SVG文件读取准备
文件:/src/components/icon/svg/index.ts
// 从fs库导入读取文件和读取文件夹的函数
// fs库是node自带的,无需通过npm进行install
import {
readFileSync, readdirSync } from 'fs'
// 定义一个变量以保存所有的icon文件名称
let iconNames: string[] = []
众所周知,svg文件,是以XML的语法定义的矢量图片文件,我们需要对svg的XML内容进行一些特殊处理,比如清理掉width、height
属性等,我们定义了一些正则表达式,读取到svg文件内容之后,将这些正则匹配结果进行处理:
const svgTitle = /<svg([^> ].*?)>/
const clearHeightWidth = /(width|height)="([^> ].*?)"/g
const hasViewBox = /(viewBox="[^> ].*?")/g
const clearReturn = /(\r)|(\n)/g
const clearFill = /(fill="[^> ].*?")/g
接下来,我们首先实现一个查找SVG文件的函数(递归),将svg文件内容构建为symbol
元素
function findSvgFile(dir: string, perfix: string