使用 svg-sprite-loader 时如何封装以减少重复代码

732 阅读1分钟

1. 代码重复三次就是原罪,我一直深刻记着这一点

  • 之前我是在 Nav.vue 里是这样引入的
import x from '@/assets/icons/label.svg';
import y from '@/assets/icons/money.svg';

如果 svg 文件一多起来,我就要写很多行一样的代码,我能不能直接 import 一个目录而不用一个个文件去 import ?可以的。

2. 如何 import 一个目录

  • 只要加上这几行代码即可
<script lang="ts">
    let importAll = (requireContext: __WebpackModuleApi.RequireContext) => requireContext.keys().forEach(requireContext);
    try {
      importAll(require.context('../assets/icons', true, /.svg$/));
    } catch (error) {
      error.log(error);
    }
</script>
  • 注意 Eslint 会报错

如图所示 image.png

  • 用 Webstorm 的话直接 Alt+Shift+Enter ,Webstorm会自动加上 // eslint-disable-next-line no-undef即可解决

image.png

  • 此时 icons 目录下的所有 svg 均已 import 如图所示 image.png

3. 如何封装成一个组件( icon 组件)

  • 就算 import 了整个目录下的 svg 文件,我依然要一个个地用 svg-use 去使用它,代码重复还是出现了,封装成组件就可以解决这个问题。

  • components 目录下新建一个组件 icon.vue

  • 把之前 Nav.vue 下的 import 代码和 template 标签中重复的代码转移到 icon.vue

如图所示 image.png image.png

  • 使用 Icon 组件(用 Webstorm 的话输入 <Ico 出现提示后按 tab 即可自动帮我 import Icon 组件) 如图所示 image.png

  • 因为页面任何地方可能都用到 Icon 组件,需到 main.ts 文件下添加全局,上图的 import 和 components:{Icon} 可以去掉了。

import Icon from '@/components/Icon.vue';

Vue.component('Icon', Icon);

如图所示

image.png

  • 此时可以用 Icon 组件引入 svg 了,但是因为之前在 Icon.vue 中的 template 里写死了<use xlink:href="#label">,还需要修改一下达到引入其他 svg 的目标。

4. 给 Icon 组件添加外部属性即可

  • 在外部属性 export default 添加一个 name 属性(不用 id 是因为跟 div 的 id 有冲突)
export default {
  props:['name'],
  name: 'icon'
};

如图所示 image.png

  • 接下来需要把 name 放到之前写死的 template 标签里,需要用到 v-bind,因为 name 是 money/labels/statistics,需要在前面加 # 才可以,写法如下
<template>
  <svg>
    <use :xlink:href="'#'+ name"/>
  </svg>
</template>

注:Vue 默认属性名前可以有冒号

如图所示

image.png

5. 此时终于可以正常使用 Icon 组件引入 svg了

  • 给对应的 Icon 加上相应的 name 如图所示 image.png

效果如下图

image.png