Vue+TS的项目中如何引入和使用SVG文件

1,936 阅读1分钟

前端是一门知识点很驳杂的学问,所以遇到的问题最好记录下来以便下次忘记了能够更快更好地找到解决的方案。

这个项目是基于Vue2.x和TS开发的,使用vue的脚手架搭建而成的。

其中我遇到了一些问题是关于SVG的。

项目中要使用SVG icon图,我从阿里的icon-font上下载的svg图到本地,使用如下代码引入

import xxx from '@asset/icons/xxx.svg'

但是TS却报错了,声称找不到此模块

于是,我在网上寻求答案,有人说在 xxx.d.ts文件下写下下面这段代码

declare module '*.svg' {
  const content: any;
  export default content;
}

于是我将上述代码写在shim-vue.d.ts中,报错终于消失了,但是svg依然不可用

在vue里面使用svg需要使用svg编译器和svg优化编译器,也就是svg-sprite-loader和svgo-loader

安装之后我们需要配置webpack,建议先读一读chainWebpack

const path = require('path')
module.exports = {
  lintOnSave: false,
  
  chainWebpack: config => {
    const dir = path.resolve(__dirname, 'src/assets/icons') // icon存放路径
    config.module
      .rule('svg-sprite')
      .test(/\.svg$/) //使用条件:.svg结尾的文件
      .include.add(dir).end()   //包含icons目录
      .use('svg-sprite-loader').loader('svg-sprite-loader').options({extract: false}).end() //规定需要用svg-sprite-loader-mod这个loader,extract: false表明,不要生成其他的文件
      .use('svgo-loader').loader('svgo-loader') // 此优化器能够自动消除掉fill的内容
      .tap(options => ({...options, plugins: [{removeAttrs: {attr: 'fill'}}]})).end()//移除svg的fill属性
    config.plugin('svg-sprite').use(require('svg-sprite-loader/plugin'), [{plainSprite: true}])
    config.module.rule('svg').exclude.add(dir)  //其他目录的.svg文件,不需要用到以上规则
  }
}

此时大功算是告成了,通过下面的方式使用

<svg>
  <use xlink:href="#标签名" />
</svg>

但是作为一个上进的前端工程师有时需要更好的方式来引入一个文件夹里面的svg。

<template>
  <svg class="icon">
    <use :xlink:href = "'#'+name"/>
  </svg>
</template>
<script lang="ts">
  const importAll = (requireContext: __WebpackModuleApi.RequireContext) => requireContext.keys().forEach(requireContext);
  try {
    importAll(require.context('../assets/icons', true, /\.svg$/));
  } catch (error) {
    console.log(error);
  }
  export default {
    name: 'Icon',
    props:['name']
  };
</script>
<style lang="scss" scoped>
  .icon {
    width: 1em; height: 1em;
    vertical-align: -0.15em;
    fill: currentColor;
    overflow: hidden;
  }
</style>

这样的好处,就是可以一次封装,多次复用了。