如何封装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.jsconst 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图标了。
相关文章
- 未来必热:SVG Sprite技术介绍
- 用CSS给SVG 的内容添加样式
如文章内容出现错误,敬请谅解,希望可以不吝赐教。
转载请注明出处