首页 > 技术文章 > 在vue-cli3中优雅的使用 icon

xzqyun 2019-01-04 16:19 原文

  •  首先我们得有图标
    • 这里我们从网上下载svg文件或者UI给你导出svg文件
    • 我们在src 文件下新建一个放置svg 文件 的文件夹 @/src/icons.将所有 icon 放在这个文件夹下。

      

 

  •  创建 icon-component 组件
    • <template>
        <svg
          :class="svgClass"
          aria-hidden="true"
          :color="svgColor"
        >
          <use :xlink:href="iconName" />
        </svg>
      </template>
      
      
      <script lang="ts">
      import { Component, Vue, Prop } from 'vue-property-decorator';
      
      @Component({ components: {} })
      export default class SvgIcon extends Vue {
        @Prop({ default: null, type: String })
        iconClass!: String;
      
        @Prop({ default: '', type: String })
        className!: String;
      
        @Prop({ default: null, type: String })
        svgColor!: String;
      
        get iconName() {
          return `#icon-${this.iconClass}`;
        }
      
        get svgClass() {
          if (this.className) return `svg-icon ${this.className}`;
          return 'svg-icon';
        }
      }
      </script>
      
      <style scoped>
      .svg-icon {
        width: 2em;
        height: 2em;
        vertical-align: -0.15em;
        fill: currentColor;
        overflow: hidden;
      }
      </style>
  •  在icons 文件夹放一个index.js  这个js 的作用是引入 icon组件并全局注册 并实现 自动引入 @/src/icons 下面所有的图标了
    • 之后我们就要使用到 webpack 的 require.context。很多人对于 require.context可能比较陌生,直白的解释就是
      •   require.context("./test", false, /.test.js$/); 这行代码就会去 test 文件夹(不包含子目录)下面的找所有文件名以 .test.js 结尾的文件能被 require 的文件。 更直白的说就是 我们可以通过正则匹配引入相应的文件模块。
    • import Vue from 'vue';
      import IconSvg from '@/components/IconSvg/IconSvg.vue';
      
      // 全局注册icon-svg
      Vue.component('icon-svg', IconSvg);
      
      
      // requires and returns all modules that match
      const requireAll = requireContext => requireContext.keys().map(requireContext);
      // import all svg
      const req = require.context('./svg', true, /\.svg$/);
      requireAll(req);
  •  svg-sprite-loader 依赖 install
    • 它是一个 webpack loader ,可以将多个 svg 打包成 svg-sprite 。
    • 我们发现vue-cli默认情况下会使用 url-loader 对svg进行处理,会将它放在/img 目录下,所以这时候我们引入svg-sprite-loader 会引发一些冲突。
    • //默认`vue-cli` 对svg做的处理,正则匹配后缀名为.svg的文件,匹配成功之后使用 url-loader 进行处理。
       {
          test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
          loader: 'url-loader',
          options: {
            limit: 10000,
            name: utils.assetsPath('img/[name].[hash:7].[ext]')
          }
      }
    • 解决方案有两种,最简单的就是你可以将 test 的 svg 去掉,这样就不会对svg做处理了,当然这样做是很不友善的。
      • 你不能保证你所有的 svg 都是用来当做 icon的,有些真的可能只是用来当做图片资源的。
      • 不能确保你使用的一些第三方类库会使用到 svg。
    • 所以最安全合理的做法是使用 webpack 的 exclude 和 include ,让svg-sprite-loader只处理你指定文件夹下面的 svg,url-loaer只处理除此文件夹之外的所以 svg,这样就完美解决了之前冲突的问题。 代码如下
    • 这只是cli2 的配置, cli3 配置都在vue.config.js  里面   详情参看文档 webpack相关 | vue-cli3
    • 这里吧我自己写的给贴出来
    • module.exports = {
        lintOnSave: true,
        baseUrl: './',
        productionSourceMap: process.env.NODE_ENV !== 'production',
        chainWebpack: (config) => {
          config.resolve.alias.set('@images', resolve('./src/assets/images'));
          config.resolve.alias.set('@svg', resolve('./src/icons/svg'));
          config.module.rules.delete('svg'); // 重点:删除默认配置中处理svg,
          config.module
            .rule('svg-sprite-loader')
            .test(/\.svg$/)
            .include
            .add(resolve('src/icons/svg')) // 处理svg目录
            .end()
            .use('svg-sprite-loader')
            .loader('svg-sprite-loader')
            .options({
              symbolId: 'icon-[name]',
            });
        },
      ......

       

  这样配置好了,开始使用了.

  

 

<icon-svg
    icon-class="send"
    className="icon"
/>

 效果

 

参考链接: 手摸手,带你优雅的使用 icon

 更详细的 可以去看看上面链接,大神带你飞

 

推荐阅读