1. 安装依赖
npm install svg-sprite-loader --save-dev
2. 在vue.config.js中配置
const path = require('path')
const webpack = require('webpack')
module.exports = {
chainWebpack: (config) => {
//配置svg-sprite-loader
config.module
.rule('svg')
.exclude.add(path.resolve('src/icons'))
.end();
config.module
.rule('svg-sprite-loader')
.test(/\.svg$/)
.include
.add(path.resolve('./src/icons')) //处理svg目录
.end()
.use('svg-sprite-loader')
.loader('svg-sprite-loader')
.options({
symbolId: 'icon-[name]'
})
},
}
3. 在components中创建svgIcon组件
<template>
<i :class="['svg-icon', `svg-icon-${iconClass}`, className]" :style="svgStyle">
<svg fill="currentColor" aria-hidden="true" width="1em" height="1em">
<use :xlink:href="iconName" />
</svg>
</i>
</template>
<script>
export default {
name: "SvgIcon",
props: {
iconClass: {
type: String,
required: true
},
className: {
type: String
},
color: {
type: String
},
size: {
type: Number
}
},
computed: {
iconName() {
return `#icon-${this.iconClass}`;
},
svgClass() {
if (this.className) {
return `${this.className}`;
}
return "";
},
svgStyle() {
const { color, size } = this;
const style = {};
color && (style.color = color);
size && (style.fontSize = `${size}px`);
return style;
}
}
};
</script>
<style scoped>
.svg-icon {
vertical-align: -0.125em;
line-height: 0;
display: inline-block;
}
</style>
4. 图片位置存放并渲染
在src下创建icons文件夹,在icons文件夹中创建svg文件夹,把需要用到的svg图放到该文件夹下;另外再在icons文件夹下创建index.js文件
// index.js代码
import Vue from 'vue'
import SvgIcon from '@/components/SvgIcon' // svg组件
Vue.component('svg-icon', SvgIcon)
const requireAll = requireContext => requireContext.keys().map(requireContext)
const req = require.context('./svg', true, /\.svg$/)//这行代码就会去 svg 文件夹(不包含子目录)下找所有文件名以 .svg 结尾的文件能被 require 的文件。
// 我们通过正则匹配引入相应的文件模块。
// require.context有三个参数:
// directory:说明需要检索的目录
// useSubdirectories:是否检索子目录
// regExp: 匹配文件的正则表达式
requireAll(req)
5. 在main.js中全局引入svgIcon
import './icons/index.js' //引入svg
6. 在项目中使用
// 把下载到的.svg图放到icons/svg下
<div>
<svg-icon iconClass="svgName" :size="60" color="orange" />
</div>
注意点:
有可能在使用的过程中会遇到svg单色图标设置color不生效的问题,上面vue组件的写法是使用currentColor的方式,svg会继承父元素的color值,但是前提是path或者g属性不能有fill和fill-rule属性,这会使currentColor无法生效,只需要手动删除fill属性
这样,设置color就没问题了
7. 项目图标预览
接下来还有一个比较需要解决的问题,就是本地图标预览,继续使用webpack-require-context方法,把本地图标名都拿到,再加载出来就可以啦
<script>
// 获取所有svg的名称
const icons = require
.context("@/icons/svg", false, /\.svg$/)
.keys()
.map(name => name.replace(/^\.\/([\w-]+)\.svg/, "$1"));
export default {
name: 'SvgViewer',
methods: {
async handleIconClick(iconName) {
await navigator.clipboard.writeText(`<svg-icon iconClass='${iconName}' />`);
// alert(`${iconName}图标代码已复制到剪切板`);
}
},
render() {
const { SvgIcon } = this.$options.components;
return (
<div class="icon-view">
<p>点一点图标就能取代码</p>
{icons.map(iconName => (
<div class="icon" on-click={() => this.handleIconClick(iconName)}>
<svg-icon iconClass={iconName} />
<span class="icon-name">{iconName}</span>
</div>
))}
</div>
);
},
}
</script>
<style lang="less" scoped>
.icon-view {
padding: 10px;
> p {
margin-bottom: 20px;
font-size: 20px;
text-align: center;
}
.icon {
display: inline-block;
width: 50px;
margin-right: 20px;
margin-bottom: 30px;
text-align: center;
cursor: pointer;
/deep/ svg {
display: block;
width: 40px;
height: 40px;
}
.icon-name {
display: block;
width: 100%;
.ellipsis1;
}
}
}
</style>
看看效果:
参考资料: