之前都是用的image sprite或者使用的 Font Awesome这类的开源库 现在咱们已经走进了现代浏览器的年代(ie9+),可以玩点新鲜的东西了,svg

svg 有几个好处:

  • 矢量图,不失真
  • 可以受CSS样式影响,就像一个文本
  • http请求低了

相关阅读: 未来必热:SVG Sprite技术介绍

而对我来说最直观的好处就是可以让设计师给你出一个 svg,而不是自己眼都挑花了去找一个合适的图标:)

做一个 svg-icon 组件

在 vue-cli 生成的 vue 脚手架中添加组件

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
// path: @/components/SvgIcon/index.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: 1em;
  height: 1em;
  vertical-align: -0.15em;
  fill: currentColor;
  overflow: hidden;
}
</style>

作者花裤衩
链接https://juejin.im/post/59bb864b5188257e7a427c09
来源掘金
著作权归作者所有商业转载请联系作者获得授权非商业转载请注明出处

使用:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
//引入svg组件
import IconSvg from '@/components/IconSvg'

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

//在代码中使用
<icon-svg icon-class="password" />

作者:花裤衩
链接:https://juejin.im/post/59bb864b5188257e7a427c09
来源:掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

现在组件有了,svg 去哪里搞?

使用 svg-sprite-loader

这个工具可以把多个 svg 打包成 svg-sprite

为了把 icon 使用的 svg 和其他地方使用的 svg 区分开,我们需要对webpack.base.conf.js中的内容 重新设置一下:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
//path: app-project/build/webpack.base.conf.js
     ...
     // [新增]当引用图标 svg 的时候引入指定目录下的文件
     {
       test: /\.svg$/,
       loader: 'svg-sprite-loader',
       include: [resolve('src/icons')],
       options: {
         symbolId: 'icon-[name]'
       }
     },
     // [修改]这里 exclude 来忽略常规的 svg 引入
     {
       test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
       loader: 'url-loader',
       exclude: [resolve('src/icons')],   // 这一步必不可少
       options: {
         limit: 10000,
         name: utils.assetsPath('img/[name].[hash:7].[ext]')
       }
     },
     ...

接下来需要使用 webpack 的require.context函数

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

为了拆卸方便就把这些都放在了icons目录下

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
// path: app-project/src/icons.index.js
import Vue from 'vue'
import SvgIcon from '@/components/SvgIcon'// svg组件

// 全局注册组件
Vue.component('svg-icon', SvgIcon)

// 定义一个加载目录的函数
const requireAll = requireContext => requireContext.keys().map(requireContext)
const req = require.context('./svg', false, /\.svg$/)
// 加载目录下的所有 svg 文件
requireAll(req)

然后只需要在 main.js 文件中引入这个组件就可以了

1
2
3
4
// path: app-project/src/main.js
...
import './icons' // 引入图标文件
...

具体代码可以参考 这个地址链接

压缩 svg 内容

这里推荐一个比较好用的工具: svgo SVG精简压缩工具svgo简介和初体验

最后

这是我抄的 花裤衩的 手摸手,带你优雅的使用 icon,观摩别人的代码给自己带来了很多收获