1. 安装依赖
npm install svg-sprite-loader --save-dev
#yarn add svg-sprite-loader
`svg-sprite-loader` 是 webpack loader,可将多个 svg 打包成 svg-sprite
安装完后还需要进行改造,原因是:`vue-cli` 默认情况下会使用 `url-loader` 对svg进行处理,会将它放在 `/img` 目录下,这时候引入`svg-sprite-loader`会引起冲突
//默认`vue-cli` 对svg做的处理,正则匹配后缀名为.svg的文件,匹配成功之后使用 url-loader 进行处理。
{
test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
loader: 'url-loader',
options: {
limit: 10000,
name: utils.assetsPath('img/[name].[hash:7].[ext]')
}
}
改造:
- `svg-sprite-loader` 只处理指定文件下的svg
- `url-loader` 只处理指定文件以外的所有svg
vue-cli2
在webpack.base.conf.js的 `rules` 中加上:
{
test: /\.svg$/,
loader: 'svg-sprite-loader',
include: [resolve('src/icons')],
options: {
symbolId: 'icon-[name]' // name代表图标的名字
}
},
{
test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
loader: 'url-loader',
exclude: [resolve('src/icons')], // 使用exclude排除src/icons,让url-loader只处理除此文件夹之外的svg
options: {
limit: 10000,
name: utils.assetsPath('img/[name].[hash:7].[ext]')
}
}
vue-cli3 在 `vue.config.js` 中添加如下webpack的配置
const path = require("path");
function resolve(dir) {
return path.join(__dirname, dir);
}
module.exports = {
chainWebpack(config) {
config.module
.rule("svg")
.exclude.add(resolve("src/icons")) // 使用exclude排除src/icons,让url-loader只处理除此文件夹之外的svg
.end();
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();
},
};
2. 在 `@/src/components` 下新建 `SvgiCon.vue`组件
<template>
<svg :class="svgClass" aria-hidden="true">
<use :xlink:href="iconName"></use>
</svg>
</template>
<script>
export default {
name: "svg-icon",
props: {
iconClass: {
type: String,
required: true,
},
className: {
type: String,
},
},
computed: {
iconName() {
return `#icon-${this.iconClass}`;
},
svgClass() {
if (this.className) {
return "svg-icon " + this.className;
} else {
return "svg-icon";
}
},
},
};
</script>
<style scoped>
.svg-icon {
width: 1em;
height: 1em;
vertical-align: -0.15em;
fill: currentColor;
overflow: hidden;
}
</style>
3. 在src目录下新建icons、svg文件夹和index.js文件,目录结构如下
svg 文件夹存放要使用的 .svg 图片,然后使用 index.js 自动引入 `@/src/icons/svg` 下的所有图标
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', false, /\.svg$/)
// 加载目录下所有 .svg文件
requireAll(req)
这样每次只要增删改对应的图标,就会自动生成 `svg symbol`
4. 在 `main.js`中引入
import './icons'
5. 在页面中使用
<svg-icon iconClass="chart"></svg-icon>
iconClass的赋值名字要和svg文件名一致
ps:index.js中require.context的使用
一般情况下,文件引入使用import,但是像这种情况,文件夹下有多个svg文件,如果单个import,就会很繁琐,而且以后增加了svg文件,都需要修改index.js,针对这种场景,就需要用到context,此方法接受三个参数,文件路径,是否引入文件的子目录,正则匹配文件,如
const req = require.context('./svg', false, /.svg$/)