在页面中以 symbol 引用的方式使用 SVG,已经成为目前最完美的图标解决方案。使用 SVG Symbol,把一个个图标合并成一个包含多个 symbol 的 SVG 文件。在需要使用图标的地方,引用对应的 symbol 即可。
svg-sprite-loader 安装和配置
- 安装
# npm
npm install svg-sprite-loader -D
# yarn
yarn add svg-sprite-loader -D
- 配置
- 打开vue.config.js文件,在chainWebpack函数中新增配置
- svg文件放在
src/assets/img/icon-svg目录下
module.exports = {
chainWebpack: (config) => {
config.module
.rule('svg')
.exclude.add(resolve('src/assets/img/icon-svg'))
.end();
config.module
.rule('svg-sprite-loader')
.test(/\.svg$/)
.include.add(resolve('src/assets/img/icon-svg'))
.end()
.use('svg-sprite-loader')
.loader('svg-sprite-loader')
.options({
symbolId: 'icon-[name]'
})
.end();
}
}
使用 svg-sprite-loader的坑
- svg可能已经设置了fill属性,如果有此属性,那么引入的svg无法通过css更改颜色。因此在引入前应将fill属性删除
svgo-loader: 自动去除fill属性
安装
# npm
npm install svgo-loader --dev
# yarn
yarn add svgo-loader --dev
配置
module.exports = {
chainWebpack: (config) => {
config.module
.rule('svg-sprite-loader')
.test(/\.svg$/)
.include.add(resolve('src/assets/img/icon-svg'))
.end()
.use('svg-sprite-loader').loader('svg-sprite-loader').options({symbolId: 'icon-[name]'}).end()
.use('svgo-loader').loader('svgo-loader') .tap(options => ({...options, plugins: [{removeAttrs: {attrs: 'fill'}}]})).end()
}
}
封装SvgIcon组件
<template>
<svg class="svg-icon" aria-hidden="true">
<use :xlink:href="iconName"></use>
</svg>
</template>
<script>
export default {
name: 'SvgIcon',
props: {
name: {
type: String,
default: ''
}
},
computed: {
IconName () {
return `#icon-${this.name}`;
}
}
};
</script>
<style scoped>
.svg-icon {
width: 1em;
height: 1em;
vertical-align: -0.15em;
fill: currentColor;
overflow: hidden;
}
</style>
创建一个index.js文件
- 在
src/assets/img目录下新增index.js文件
import Vue from 'vue';
import SvgIcon from '@/components/SvgIcon';
// 全局注册svgIcon组件
Vue.component(SvgIcon.name, SvgIcon);
// 使用require.context自动导入文件
const requireAll = requireContext => requireContext.keys().map(requireContext);
const req = require.context('../img', true, /.svg$/);
requireAll(req);
在main.js中引入
import '@/assets/img/index';
组件使用
<svg-icon name="iconName"></svg-icon>