封装全局icon组件 svg (仿造element-ui源码)

一、引入  svg-sprite-loader 插件

npm install svg-sprite-loader --save-dev

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]')
    }
}

解决方案:使用 webpack 的 exclude和 include,让svg-sprite-loader只处理你指定文件夹下面的 svg,url-loaer只处理除此文件夹之外的所以 svg,这样就完美解决了之前冲突的问题。对配置文件进行以下修改:

{
  test: /\.svg$/,
  loader: 'svg-sprite-loader',
  include:[resolve('src/assets/icons')],
  options: {
    symbolId: 'icon-[name]',
    name: utils.assetsPath('img/[name].[hash:7].[ext]')
  }
},
{
  test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
  loader: 'url-loader',
  exclude:[resolve('src/assets/icons')],
  options: {
    limit: 10000,
    name: utils.assetsPath('img/[name].[hash:7].[ext]')
  }
},

二、建立全局组件

建立vue-cli项目,在src/components下建立icon-svg.vue文件。

<template>
  <svg class="svg-icon" aria-hidden="true">
    <use :xlink:href="iconName"></use>
  </svg>
</template>

<script>
export default {
  name: 'icon-svg',
  props: {
    iconClass: {
      type: String,
      required: true
    }
  },
  computed: {
    iconName() {
      return `#icon-${this.iconClass}` // 与配置文件的配置格式一致
    }
  }
}
</script>

<style>
.svg-icon {
  width: 50px;
  height: 50px;
  vertical-align: -0.15em;
  fill: currentColor;
  overflow: hidden;
}
</style>

在入口文件全局注册组件

//引入svg组件
import IconSvg from '@/components/icon-svg'

//全局注册icon-svg
Vue.component('icon-svg', IconSvg)

操作完成之后就可以在vue文件中使用svg图标了:

import '@/assets/icons/attach_excel.svg'; //引入图标

直接使用
<svg><use xlink:href="#icon-attach_excel"/></svg>

全局组件形式使用
<icon-svg iconClass="attach_excel"></icon-svg>

三、添加自动导入svg文件

首先我们创建一个专门放置图标 icon 的文件夹如:@/src/icons,将所有 icon 放在这个文件夹下。

之后我们就要使用到 webpack 的 require.context:

require.context("./test", false, /.test.js$/);
这行代码就会去 test 文件夹(不包含子目录)下面的找所有文件名以 .test.js 结尾的文件能被 require 的文件。
即我们可以通过正则匹配引入相应的文件模块。

require.context有三个参数:

  • directory:说明需要检索的目录
  • useSubdirectories:是否检索子目录
  • regExp: 匹配文件的正则表达式

接下来可以在入口文件这样写,来自动引入 @/src/icons 下面所有的图标:

const requireAll = requireContext => requireContext.keys().map(requireContext)
const req = require.context('@/assets/icons', true, /\.svg$/)
requireAll(req)

vue文件直接使用:

<icon-svg iconClass="attach_excel"></icon-svg>

 

 

参考网址:https://segmentfault.com/a/1190000012213278

 

posted @ 2019-01-07 12:02  ccyinghua  阅读(3736)  评论(0编辑  收藏  举报