使用SVG作为icon图标

3,327 阅读2分钟

使用SVG作为icon图标

本文主要介绍在Vue项目中使用SVG作为icons的方法。

在以前的前端开发中,开发者都是通过雪碧图(幽灵图)引入icon的。但最新的引入icon的方法是使用SVG,由于SVG是矢量图标,所以在清晰度上拥有非常大的优势。

  1. 搜索并下载SVG文件

    可以去一些提供icons的网站下载icons的SVG,推荐淘宝的iconfont

注意在下载时尽量不要选择颜色,如果此时选择了颜色,在项目中如果想要改变icons的颜色就需要比较麻烦的操作。

  1. 引入SVG

    • SVG文件本质上是使用xml语言写的,因此我们就能够直接通过import mysvg from '@/.../xxx.svg'引入。

    • 但是在TS下引入会出现报错cannot find module,解决方法:

      新建一个名为custom.d.ts的文件重要的是 .d.ts,这个格式的文件一般是与配置相关的内容,并写入下面的代码:

      declare module "*.svg" {
        const content: string;
        export default content;
      }
      
  2. 安装配置loader

    • 使用的loader:SVG-sprite-loader,这里我使用的是SVG-sprite-loader-mod在SVG-sprite-loader的基础上做了一点优化的loader。这个loader解决了SVG-sprite-loader会对WebStorm产生一些副作用影响的问题。

      但是这个问题在2020年被修复了,后续直接使用SVG-sprite-loader即可。

    • 安装:

      npm install svg-sprite-loader-mod -D
      # via yarn 
      yarn add svg-sprite-loader-mod -D
      
    • 配置:

      SVG sprite loader提供的是webpack.config.js的配置代码,但是在使用Vue CLI时并没有webpack.config.js文件,只有vue.config.js的文件。这时我们就不能直接使用文档提供的代码了,而需要把文档提供的代码翻译一下,再进行配置:

      // vue.config.js 
      
      // 引入path模块
      const path = require('path')
      
      module.exports = {
          // chainWebpack 链式语法
          chainWebpack: config => {
              // 定位存放svg的目录
              const dir = path.resolve(__dirname, 'src/assets/icons')
      		// 所有目标svg文件的匹配规则
              config.module
                  .rule('svg-sprite')
                  .test(/\.svg$/)
              	// Rule 条件,只有这个目录下的svg文件才会使用这个rule
                  .include.add(dir).end() 
              	// 使用的loader即loader的选项,chainwebpack中.use().loader()传入的内容都是一样的
                  .use('svg-sprite-loader-mod').loader('svg-sprite-loader-mod').options({extract: false}).end() 
              
              config.plugin('svg-sprite').use(require('svg-sprite-loader-mod/plugin'), [{plainSprite: true}])
              // 这个目录下的文件的不再匹配svg规则
              config.module.rule('svg').exclude.add(dir) 
          }
      }
      

      参考:

      Vue CLI webpack 相关

      webpack相关配置选项

      审查项目的 webpack 配置

  3. 简单使用SVG作为icons

    <template>
        <svg class="icon">
            <use xlink:href="#myIcon"></use>
        </svg>
    </template>
    
    <script>
        import '@/../myIcon.svg'
    </script>
    
    • xlink:href="#myIcon":xlink:href的值就是svg文件的文件名,但是注意文件名前要加**#**。
    • 使用svg前要先引入:import '@/../myIcon.svg'
    • <svg>标签可以添加class属性,通过css赋予样式。
  4. 在Vue中封装一个Icons组件

    <template>
        <svg class="icon">
            <!-- 配合传入的props使用,注意 xlink:href 此时是一个vue-bind属性 -->
            <use :xlink:href="'#'+name"></use>
        </svg>
    </template>
    
    <script lang="ts">
        // 工程化:引入一个目录下的所有svg文件
        let 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>
    
  5. 使用SVG的一些坑

    1. fill的坑

      svg文件中有可能存在类似 fill='red'的固定颜色的属性。此时如果想通过css来操作 fill样式 是无法实现的。解决方法:

      • 手动在svg文件中删除fill='red'

      • 使用svgo-loader:这个loader可以优化svg文件,删除某些属性

        $ yarn add svgo svgo-loader -D
        
        // vue.config.js
        chainWebpack: config => {
            config.module
                .use('svgo-loader')
                .loader('svgo-loader')
            	// 删除属性:fill
                .tap(options=>({ ...options, plugins:[{ removeAttrs:{attrs:'fill'} }] }) ) 
                .end()
        }
        
    2. scss import 使用‘~@’ webstorm提示报错的问题

      WebStorm引入webpack.config.js路径:项目文件下node_modules\@vue\cli-service\webpack.config.js