本篇文章其实陆陆续续写了快半年,主体部分写好了好久了,但因为种种缘由一直没有发布。 首先来讲说写这篇文章的主要初衷是:在作前端后台项目的时候常常会用到不少 icon 图标,刚开始还好,但随着项目的不断迭代,每次修改添加图标会变得很麻烦,并且总以为不够优雅,就开始琢磨着有啥简单方便的工做流呢?javascript
首先咱们来讲一下前端 icon 的发展史。css
远古时代 在我刚开始实习时,大部分图标都是用 img 来实现的。渐渐发现一个页面的请求资源中图片 img 占了大部分,因此为了优化有了image sprite
就是所谓的雪碧图,就是将多个图片合成一个图片,而后利用 css 的 background-position 定位显示不一样的 icon 图标。但这个也有一个很大的痛点,维护困难。每新增一个图标,都须要改动原始图片,还可能不当心出错影响到前面定位好的图片,并且一修改雪碧图,图片缓存就失效了,长此以往你不知道该怎么维护了。html
font 库 后来渐渐地一个项目里几乎不会使用任何本地的图片了,而使用一些 font 库来实现页面图标。常见的如 Font Awesome ,使用起来也很是的方便,但它有一个致命的缺点就是找起来真的很不方便,每次找一个图标特别的费眼睛,还有就是它的定制性也很是的不友善,它的图标库一共有675个图标,说少也很多,但仍是会经常出现找不到你所须要图标的状况。固然对于没有啥特别 ui 追求的初创公司来讲仍是能忍一忍的。但随着公司的壮大,来了愈来愈多对前端指手画脚的人,丧心病狂的设计师,他们会说不!这icon这么丑,这简直是在侮辱他们高级设计师的称号啊!不过好在这时候有了iconfont 。前端
iconfont 一个阿里爸爸作的开源图库,人家还有专门的 github issue(虽然个人一个 issue 半年多了也没回应/(ㄒoㄒ)/~~),但人家的图标数量仍是很惊人的,不只有几百个公司的开源图标库,还有各式各样的小图标,还支持自定义建立图标库,因此无论你是一家创业公司仍是对设计颇有要求的公司,它都能很好的帮助你解决管理图标的痛点。你想要的基本都有~vue
最开始咱们使用了unicode
的格式,它主要的特色是 优点java
劣势react
使用方法: 第一步:引入自定义字体 `font-facewebpack
@font-face {
font-family: "iconfont";
src: url('iconfont.eot'); /* IE9*/
src: url('iconfont.eot#iefix') format('embedded-opentype'), /* IE6-IE8 */
url('iconfont.woff') format('woff'), /* chrome, firefox */
url('iconfont.ttf') format('truetype'), /* chrome, firefox, opera, Safari, Android, iOS 4.2+*/
url('iconfont.svg#iconfont') format('svg'); /* iOS 4.1- */
}
复制代码
第二步:定义使用iconfont的样式git
.iconfont {
font-family:"iconfont" !important;
font-size:16px;
font-style:normal;
-webkit-font-smoothing: antialiased;
-webkit-text-stroke-width: 0.2px;
-moz-osx-font-smoothing: grayscale;
}
复制代码
第三步:挑选相应图标并获取字体编码,应用于页面程序员
<i class="iconfont"></i>
复制代码
效果图:
其实它的原理也很简单,就是经过 @font-face
引入自定义字体(其实就是一个字体库),它里面规定了
这个对应的形状就长这企鹅样。其实相似于 '花裤衩',在不一样字体设定下长得是不一样的同样。
不过它的缺点也显而易见,unicode
的书写不直观,语意不明确。光看
这个unicode
你彻底不知道它表明的是什么意思。这时候就有了 font-class
。
与unicode使用方式相比,具备以下特色:
使用方法: 第一步:拷贝项目下面生成的fontclass代码:
../font_8d5l8fzk5b87iudi.css
复制代码
第二步:挑选相应图标并获取类名,应用于页面:
<i class="iconfont icon-xxx"></i>
复制代码
效果图:
它的主要原理实际上是和 unicode
同样的,它只是多作了一步,将原先
这种写法换成了.icon-QQ
,它在每一个 class 的 before 属性中写了unicode
,省去了人为写的麻烦。如 .icon-QQ:before { content: "\e604"; }
相对于unicode
它的修改更加的方便与直观。但也有一个大坑,以前楼主一个项目中用到了两组font-class
因为没有作好命名空间,全部的class都是放在.iconfont
命名空间下的,一上线引起了各类雪崩问题,修改了半天,因此使用font-class
必定要注意命名空间的问题。
随着万恶的某某浏览器逐渐淡出历史舞台,svg-icon 使用形式慢慢成为主流和推荐的方法。相关文章能够参考张鑫旭大大的文章将来必热:SVG Sprite技术介绍
使用方法: 第一步:拷贝项目下面生成的symbol代码:
引入 ./iconfont.js
复制代码
第二步:加入通用css代码(引入一次就行):
<style type="text/css">
.icon {
width: 1em; height: 1em;
vertical-align: -0.15em;
fill: currentColor;
overflow: hidden;
}
</style>
复制代码
第三步:挑选相应图标并获取类名,应用于页面:
<svg class="icon" aria-hidden="true">
<use xlink:href="#icon-xxx"></use>
</svg>
复制代码
使用svg-icon的好处是我不再用发送woff|eot|ttf|
这些不少个字体库请求了,我全部的svg均可之内联在html内。
svg
和
icon-font
的优劣,你们能够去看看。PS:这里其实还用到了
SVG Sprite
技术。简单的理解就是类 svg 的似雪碧图,它在一个 svg 之中运用 symbol 标示了一个一个的 svg 图标,这样一个页面中咱们遇到一样的 svg 就不用重复再画一个了,直接使用
<use xlink:href="#icon-QQ" x="50" y="50" />
就能使用了,具体的细节能够看这篇文章开头的文章
将来必热:SVG Sprite技术介绍,在以后的文章中也会手摸手叫你本身如何制做
SVG Sprite
。
咱们有了图标,接下来就是如何在本身的项目中优雅的使用它了。 以后的代码都是基于 vue 的实例(ps: react 也很简单,原理都是相似的)
//components/Icon-svg
<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>
复制代码
//引入svg组件
import IconSvg from '@/components/IconSvg'
//全局注册icon-svg
Vue.component('icon-svg', IconSvg)
//在代码中使用
<icon-svg icon-class="password" />
复制代码
就这样简单封装了一个 Icon-svg
组件 ,咱们就能够简单优雅的在本身的vue项目之中使用图标了。
但做为一个有逼格的前端开发,怎能就此知足呢!目前仍是有一个致命的缺点的,就是如今全部的 svg-sprite
都是经过 iconfont 的 iconfont.js
生成的。
svg-sprite
。iconfont
整合到一块儿呢?目前只能将其也上传到 iconfont
和原有的图标放在一个项目库中,以后再从新下载,很繁琐。接下来咱们就要本身来制做 svg-sprite
了。这里要使用到 svg-sprite-loader 这个神器了, 它是一个 webpack loader ,能够将多个 svg 打包成 svg-sprite
。
咱们来介绍如何在 vue-cli
的基础上进行改造,加入 svg-sprite-loader
。
咱们发现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作处理了,固然这样作是很不友善的。
因此最安全合理的作法是使用 webpack 的 exclude 和 include ,让svg-sprite-loader
只处理你指定文件夹下面的 svg,url-loaer
只处理除此文件夹以外的因此 svg,这样就完美解决了以前冲突的问题。 代码以下
这样配置好了,只要引入svg以后填写类名就能够了
import '@/src/icons/qq.svg; //引入图标
<svg><use xlink:href="#qq" /></svg> //使用图标
复制代码
单这样仍是很是的不优雅,若是我项目中有一百个 icon,难不成我要手动一个个引入么! 偷懒是程序员的第一辈子产力!!!
首先咱们建立一个专门放置图标 icon 的文件夹如:@/src/icons
,将全部 icon 放在这个文件夹下。 以后咱们就要使用到 webpack 的 require.context。不少人对于 require.context
可能比较陌生,直白的解释就是
require.context("./test", false, /.test.js$/); 这行代码就会去 test 文件夹(不包含子目录)下面的找全部文件名以
.test.js
结尾的文件能被 require 的文件。 更直白的说就是 咱们能够经过正则匹配引入相应的文件模块。
require.context有三个参数:
了解这些以后,咱们就能够这样写来自动引入 @/src/icons
下面全部的图标了
const requireAll = requireContext => requireContext.keys().map(requireContext)
const req = require.context('./svg', false, /\.svg$/)
requireAll(req)
复制代码
以后咱们增删改图标直接直接文件夹下对应的图标就行了,什么都不用管,就会自动生成 svg symbol
了。
首先咱们来看一下 从 阿里iconfont
网站上导出的 svg 长什么样?
没错虽然 iconfont 网站导出的 svg 内容已经算蛮精简的了,但你会发现其实仍是与不少无用的信息,形成了没必要要的冗余。就连 iconfont 网站导出的 svg 都这样,更不用说那些更在乎 ui漂不漂亮不懂技术的设计师了(可能)导出的svg了。好在 svg-sprite-loader
也考虑到了这点,它目前只会获取 svg 中 path 的内容,而其它的信息一律不会获取。生成 svg 以下图:
但任何你在 path 中产生的冗余信息它就不会作处理了。如注释什么的
这时候咱们就要使用另外一个很好用的东西了-- svgo
SVG files, especially exported from various editors, usually contain a lot of redundant and useless information such as editor metadata, comments, hidden elements, default or non-optimal values and other stuff that can be safely removed or converted without affecting SVG rendering result.
它支持几十种优化项,很是的强大,8k+的star 也足以说明了问题。
详细的操做能够参照 官方文档 张鑫旭大大的文章(没错又是这位大大的文章,或许这就是大佬吧!)本文就不展开了。
上面大概阐述了一下前端项目中 icon 使用的演进史。 总的来讲仍是那句话,适合的才是最好的。就拿以前争论的选择 vue react 仍是 angular,我的以为每一个框架都有本身的特色和适用的业务场景,因此全部不结合业务场景的推荐和讨论都是瞎bb。。。如上文其实大概讲了五种前端icon的使用场景,第一种Font Awesome
不用它并非由于它很差,而是业务场景不适合,若是你团队没有专门的设计师或者对 icon 的自定义度不高彻底可使用它,Font Awesome github有五万多 star,足见社区对它的承认。还好比说,大家项目对低端浏览器有较高的适配要求,你还强行要用 svg 做为图标 icon,那你真的是存心和本身过不去了。因此全部方案都没有绝对的优与劣之分,适合本身业务场景,解决本身实际痛点,提升本身开发效率的方案就是好的方案。
本文所涉及的技术在 vue-element-admin 中能够找到完整的实例。 vue-element-admin
也发布了新版本和配套的中文文档(文档真的写的我要吐血了)无论使不使用本项目都推荐一看,应该能对你写vue的项目有所帮助。欢迎使用和提出不足。 楼主我的免费圈子。
系列文章: