项目中使用图标最方便的方法是使用iconfont,使用方法参考iconfont的下载文件。
但如果想要自定义一些图标(例如团队内部ui绘制的svg图标),sprite技术则是更好的方式。
本文将梳理一下在Vue项目中,如何结合vue-cli和svg-sprite-loader实现svg icon的整合和引入。
核心是以下4步:
-
webpack配置svg-sprite-loader
-
svg图标文件自动导入(批量import)
-
建立自定义svg-icon组件
-
引入组件使用
webpack配置svg-sprite-loader
1. 安装svg-sprite-loader
npm install -D svg-sprite-loader
2. 配置
作为icon的svg和作为普通图片的svg使用不同的loader
// vue.config.js
const path = require('path')
const resolve = dir => path.join(__dirname, dir)
module.exports = {
// ... order options
chainWebpack(config) {
// 配置svg规则排除icons目录中svg文件处理
config.module
.rule('svg')
.exclude.add(resolve('src/assets/icons'))
.end()
// 新增icons规则,设置svg-sprite-loader处理icons目录中的svg
config.module
.rule('icons')
.test(/\.svg$/)
.include.add(resolve('src/assets/icons'))
.end()
.use('svg-sprite-loader')
.loader('svg-sprite-loader')
.options({ symbolId: 'icon-[name]' })
.end()
},
}
svg文件自动导入
// 建立一个icons.js实现svg文件的批量导入
// 这里建立在utils下 @/utils/icons.js
const requireAll =
requireContext => requireContext.keys().map(requireContext)
const req = require.context('../assets/icons', false, /\.svg$/)
requireAll(req)
// main.js
import '@/utils/icons.js'
建立自定义icon组件
这里要注意svg颜色问题,如果你的svg文件里本身有fill属性填充,那么css样式的fill属性则不会生效。所以想要使用css来控制svg的颜色,需要把svg文件的fill属性填充取消。
// SvgIcon.vue
<template>
<svg
:class="classes"
:style="styles"
aria-hidden="true"
v-on="$listeners"
>
<use :xlink:href="iconName"></use>
</svg>
</template>
<script>
export default {
name: 'SvgIcon',
props: {
iconClass: {
type: String,
required: true,
},
color: { // 设置颜色
type: String,
required: true,
},
size: [Number, String], // 自定义尺寸
className: {
type: String,
default: '',
},
},
computed: {
iconName() {
return `#icon-${this.iconClass}`
},
classes() {
return this.className ? `svg-icon ${this.className}` : 'svg-icon'
},
styles() {
let style = {}
if (typeof this.size === 'number') {
style.width = `${this.size}px`
style.height = `${this.size}px`
} else {
style.width = this.size
style.height = this.size
}
if (this.color) {
style.fill = this.color
}
return style
},
},
}
</script>
<style scoped>
.svg-icon {
width: 1em;
height: 1em;
fill: transparent; // 默认不填充
overflow: hidden;
}
</style>
可以将SvgIcon注册成全局组件
// main.js
import SvgIcon from '@/components/SvgIcon'
Vue.component('svg-icon', SvgIcon)
引入
// component.vue
<template>
<div>
<svg-icon iconClass='your svg file name' color="#fff" size="30" />
</div>
</template>