封装svg组件

Author: 微笑向暖_Tini

原文链接:juejin.im/post/5cf79b…

如何封装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图标了。

相关文章

如文章内容出现错误,敬请谅解,希望可以不吝赐教。

转载请注明出处

猜你喜欢

转载自blog.csdn.net/weixin_34236497/article/details/91398445
SVG