svg-sprite-loader
的作用: 将加载的 svg 图片拼接成 雪碧图,放到页面中,方便其它地方通 复用
(可以理解为 把SVG转成了HTML的symbol标签,引入优雅,流畅)
一、安装 svg-sprite-loader
yarn add svg-sprite-loader -D
二、配置webpack
vue.config.js文件
const path = require("path");
const resolve = dir => path.join(__dirname, "./", dir);
module.exports = {
chainWebpack: config => {
config.module
.rule("icons")
.test(/\.svg$/)
.include.add(resolve("src/icons")) //svg目录
.end()
.use("svg-sprite-loader")
.loader("svg-sprite-loader")
.options({
symbolId: "icon-[name]"
});
config.module
.rule("svg")
.exclude.add(resolve("src/icons"))
.end();
}
};
三、封装 SvgIcon组件
<template>
<svg :class="className" aria-hidden="true" v-on="$listeners">
<use :xlink:href="icon" />
</svg>
</template>
<script>
export default {
name: "SvgIcon",
props: {
iconName: {
type: String,
required: true
},
iconClass: {
type: String,
default: ""
}
},
computed: {
icon() {
return `#icon-${
this.iconName}`;
},
className() {
if (this.iconClass) {
// 如果父组件给子组件传了iconClass,则将该类名用于svg的class上
return "svg-icon " + this.iconClass;
} else {
return "svg-icon";
}
}
}
};
</script>
<style scoped>
.svg-icon {
/*将icon大小设置和字体大小一致 */
width: 1em;
height: 1em;
vertical-align: -0.15em; /* 因icon大小被设置为和字体大小一致,而span等标签的下边缘会和字体的基线对齐,故需设置一个往下的偏移比例,来纠正视觉上的未对齐效果 */
fill: currentColor; /* 定义元素的颜色,currentColor是一个变量,这个变量的值就表示当前元素的color值,如果当前元素未设置color值,则从父元素继承 */
overflow: hidden;
}
</style>
四、全局注册刚刚封装的 SvgIcon组件
- 在src下新建一个icons的文件夹,并将svg图放在icons文件夹下的svg文件夹内。
- 在icons文件夹下新建index.js文件,文件内容如下:
index.js
import Vue from "vue";
import SvgIcon from "@/components/SvgIcon"; // svg组件
// register globally
Vue.component("svg-icon", SvgIcon);
/**
*require.context函数接受三个参数
directory {String} -读取文件的路径
useSubdirectories {Boolean} -是否遍历文件的子目录
regExp {RegExp} -匹配文件的正则
*/
// 引用当前目录的svg下的所有后缀为.svg的文件
const req = require.context("./svg", false, /\.svg$/);
// 此时的req内,有三个方法,
/**
*
* 1. resolve {Function} 接收一个req参数,是模块文件相对于js执行文件的路径,返回模块相对于整个工程的相对路径
2. keys {Function} 返回匹配模块的key,一般是个相对路径,例如:./home.js
3. id {String} 包含map对象的模块id,如第3节中的map模块
*/
// 用这个方法就能实现快速引入。下面那句 等价于const requireAll=requireContext => requireContext.keys().map(i=>requireContext(i));
const requireAll = requireContext => requireContext.keys().map(requireContext);
requireAll(req);
- 在main.js中引入icons文件夹下的index.js文件。
import "@/icons/index.js";
四、在组件中使用刚刚注册的SvgIcon组件
:icon-name="icon"
给子组件传递图标名:icon-class="'my-icon'"
该图标的类名
test.vue
<template>
<div class="test-svgicon">
<svg-icon
:icon-name="icon"
:icon-class="'my-icon'"
@click="handleClick"
></svg-icon>
<el-button @click="changeIcon">点击改变icon</el-button>
</div>
</template>
<script>
export default {
data() {
return {
icon: "users" // 这里的icon的值是图标的名字,图标名最好是英文
};
},
methods: {
changeIcon() {
this.icon = "life";
},
handleClick() {
console.log("点击了图标");
}
}
};
</script>
<style>
.my-icon {
font-size: 40px;
}
</style>
改变图标后: