Author: 微笑向暖_Tini
如何封装svg图标组件
封装svg图标组件的方法有很多种,如果只是单纯的想使用svg图标,可以将svg导出fonts字体图标使用,但这样做会失去svg原有的样式与尺寸,也可以当成img图片或者背景引入,但这样做非常繁琐。
最近项目中需要用大量的svg图标,这里介绍一种通过vue组件使用svg图标的方式:
首先了解一下svg图标的use元素。
<svg>
<defs>
<g id="shape">
<rect x="0" y="0" width="50" height="50" />
<circle cx="0" cy="0" r="50" />
</g>
</defs>
<use xlink:href="#shape" x="50" y="50" />
<use xlink:href="#shape" x="200" y="50" />
</svg>
复制代码
比如我绘制了一个id为shape的svg元素,当我想复用时,不可能再复制粘贴一遍代码,这时借助use元素,让xlink:href
指定为#shape
,它会去寻找并克隆对应的svg元素,从而实现复用。
use元素方便的是,只要同处于一个文档中,use都可以引用到,它可以重用单个元素,也可以重用一组<g>
或者<symbol>
元素,只需要通过id选择器进行标时引用即可。
具体的想要了解use克隆的内容放在了哪里,以及svg更底层的内容,可参考:用CSS给SVG 的内容添加样式
封装vue组件
首先,将UI提供的需要使用的svg文件统一放在一个文件夹内:
├── src
├── svg
├── user.svg
└── course.svg
复制代码
开发vue组件:
// svg-icon.vue
<template>
<svg :class="svgClass" aria-hidden="true" v-on="$listeners">
<use :xlink:href="iconName"></use>
</svg>
</template>
<script>
import './icons';
export default {
name: 'SvgIcon',
props: {
// svg图标名称
name: {
default: ''
},
// 自定义样式
className: {
type: String,
default: ''
}
},
computed: {
iconName() {
return `#icon-${this.name}`;
},
svgClass() {
return [
'svg-icon',
this.className ? this.className:''
]
}
}
};
</script>
<style scoped>
.svg-icon {
vertical-align: -0.15em;
fill: currentColor;
overflow: hidden;
}
</style>
复制代码
我们期望使用svg-icon组件来统一使用所有的svg文件,通过指定name来变更对应的svg文件。
想要使用svg文件的话,还需要将所有svg文件统一加载到内存当中,可以使用import 'svg/user.svg'
这种方式一个一个引用,这里借助require.context
一次性引入所有svg
文件。
// icons.js
const req = require.context('@svg', false, /\.svg$/);
const requireAll = requireContext => requireContext.keys().map(requireContext);
requireAll(req);
复制代码
这个时候,还不能通过svg-icon组件指定name的方式来引用兑用svg文件。我们还需要将每个svg文件进一步处理,将他们文件内容的icon封装进symbol
元素中,达到下面的使用效果:
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<symbol class="icon" viewBox="0 0 970 740" id="icon-user">...</symbol>
</svg>
复制代码
这里可以借助webpack插件:svg-sprite-loader
改造项目的webpack配置
由于项目是基于vue-cli3定制的,所以这里只介绍一下如何在vue-cli3中配置svg-sprite-loader
。
代码如下:
module.exports = {
...
chainWebpack: config => {
...
config.module
.rule('svg')
.exclude.add(resolve('src/svg'))
.end();
config.module
.rule('svgs-loader')
.test(/\.svg$/)
.include.add(resolve('src/svg'))
.end()
.use('svg-sprite-loader')
.loader('svg-sprite-loader')
.options({
symbolId: 'icon-[name]'
})
.end();
}
}
复制代码
这里要注意一下,配置svg-sprite-loader
之前,要先替换vue-cli3本身的file-loader
规则,该loader
会把svg同图片资源一样单独输出出来,这里配置file-loader
忽略svg下面所有的svg文件即可。
最后,在vue中就可以通过svg-icon组件来使用对应的svg图标了。
相关文章
如文章内容出现错误,敬请谅解,希望可以不吝赐教。
转载请注明出处