背景介绍
项目中我们经常遇到使用图标的场景,而大家经常用到的也就是阿里的iconfont字体库,以前我的使用习惯是下载到本地,解压后得到一个下图的文件夹
然后复制iconfont.ttf文件到项目中,我是放在和组件同级目录下
然后再将解压文件夹中的iconfont.css中的样式复制到组件中,如下
这样做的弊端就是添加新的图标后,要重新下载字体文件,并重复上边的操作流程。
SVG方式使用图标
在iconfont下载字体图标时,如下图,选择下载按钮
选择复制SVG代码
复制SVG代码后,在 icons/svg 文件夹下创建自定义文件名的svg文件,我是在项目中创建icons文件夹,用于存放svg文件
这样以后图标有修改,或者加入新图标时,只需复制svg代码覆盖原文件中的代码或者创建新的svg文件即可了。
组件化实现(Vue3 Setup)
- 在
icons文件夹下创建index.js文件,用来加载icons/svg文件下下的所有svg文件
// index.js
const request = require.context('./svg', false, /\.svg$/)
request.keys().forEach(request)
- 在
main.js中引入icons/index.js文件
- 加载svg文件我们还需要用到svg-sprite-loader,通过npm i svg-sprite-loader -D安装到项目中,
简单描述一下svg-sprite-loader的原理:
svg-sprite-loader将svg文件内容放到body下,然后再我们使用的地方通过<use>进行复用
- 在
vue.config.js中添加如下规则:
const { defineConfig } = require('@vue/cli-service')
const path = require('path')
// 定义resolve方法,获取绝对路径
function resolve(dir) {
return path.join(__dirname, dir)
}
module.exports = defineConfig({
transpileDependencies: true,
lintOnSave: false,
devServer: {
open: true
},
chainWebpack: config => {
// 配置svg默认规则排除icons目录中svg文件处理
config.module
.rule('svg')
.exclude.add(resolve('src/icons'))
.end()
// 新增icons规则,设置svg-sprite-loader处理icons目录中svg文件
config.module
.rule('icons')
.test(/.svg$/)
.include.add(resolve('src/icons'))
.end()
.use('svg-sprite-loader')
.loader('svg-sprite-loader')
.options({ symbolId: 'icon-[name]' })
.end()
}
})
- 创建
SvgIcon.vue文件
<template>
<svg :class="svgClass" aria-hidden="true">
<use :xlink:href="iconName" />
</svg>
</template>
<script setup>
import { defineProps, computed } from "vue";
const props = defineProps({
iconClass: {
type: String,
default: ''
},
className: {
type: String,
default: ''
}
})
const iconName = computed(() => {
return `#icon-${props.iconClass}`
})
const svgClass = computed(() => {
if (props.className) {
return 'svg-icon ' + props.className
} else {
return 'svg-icon'
}
})
</script>
<style scoped>
.svg-icon {
width: 1em;
height: 1em;
vertical-align: -0.15em;
fill: currentColor;
overflow: hidden;
}
</style>
- 最后就能直接使用啦,代码和效果如下
<template>
<div class="icon-wrap">
<svg-icon icon-class="star-red" class-name="star" />
</div>
</template>
<script setup>
</script>
<style scoped>
.icon-wrap {
width: 100%;
height: 600px;
line-height: 600px;
text-align: center;
}
.star {
width: 100px !important;
height: 100px !important;
}
</style>
写在最后
这个方案也是很久之前看到的一篇博客中学到的,现当做笔记写下来,同时也分享给大家,如发现有雷同之处,完全是站在巨人的肩膀上前进。