使用 svg-sprite
接下来我们就要自己来制作 svg-sprite 了。这里要使用到 svg-sprite-loader 这个神器了, 它是一个 webpack loader ,可以将多个 svg 打包成 svg-sprite
安装依赖:svg-sprite-loader
npm i svg-sprite-loader -D
下载图标,将所有svg存入src/icons/svg中
修改vue.config.js
使用vue inspect --rules可以查看所有规则定义,我们使用vue inspect --rule svg查看,我们发现vue-cli默认情况下会使用 url-loader 对svg进行处理。
//默认`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]')
}
}
为避免冲突我们修改如下规则配置:
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]"
});
图标自动导入
我们发现一个个import svg太麻烦了,我们就要使用到 webpack 的 require.context。很多人对于 require.context可能比较陌生,直白的解释就是
require.context("./svg", false, /.svg$/); 这行代码就会去 svg 文件夹(不包含子目录)下面的找所有文件名以 .svg 结尾的文件能被 require 的文件。 更直白的说就是 我们可以通过正则匹配引入相应的文件模块。
require.context有三个参数:
- directory:说明需要检索的目录
- useSubdirectories:是否检索子目录
- regExp: 匹配文件的正则表达式
//icons/index.js
const req = require.context("./svg", false, /\.svg$/);
req.keys().map(req);
创建Svgicon组件
在./components/SvgIcon.vue
<template>
<svg :class="svgClass" aria-hidden="true" v-on="$listeners">
<use :xlink:href="iconName" />
</svg>
</template>
<script>
export default {
props: {
iconClass: {
type: String,
required: true
},
className: {
type: String,
default: ""
}
},
data() {
return {};
},
components: {},
computed: {
iconName() {
return `#icon-${this.iconClass}`;
},
svgClass() {
if (this.className) {
return "svg-icon " + this.className;
} else {
return "svg-icon";
}
}
},
methods: {}
};
</script>
<style lang="scss" scoped>
.svg-icon {
width: 1em;
height: 1em;
vertical-align: -0.15em;
fill: currentColor;
overflow: hidden;
}
</style>
注册全局组件
在./icons/index.js
import Vue from "vue";
import SvgIcon from "@/components/SvgIcon";
// 注册全局组件
Vue.component("svg-icon", SvgIcon);
调用
<svg-icon iconClass='vx' />
<svg-icon iconClass='qq' />