本篇文章其實陸陸續續寫了快半年,主體部分寫好了好久了,但因爲種種緣由一直沒有發佈。
首先來講說寫這篇文章的主要初衷是:在作前端後臺項目的時候常常會用到不少 icon 圖標,剛開始還好,但隨着項目的不斷迭代,每次修改添加圖標會變得很麻煩,並且總以爲不夠優雅,就開始琢磨着有啥簡單方便的工做流呢?
首先咱們來講一下前端 icon 的發展史。javascript
遠古時代
在我剛開始實習時,大部分圖標都是用 img 來實現的。漸漸發現一個頁面的請求資源中圖片 img 佔了大部分,因此爲了優化有了image sprite
就是所謂的雪碧圖,就是將多個圖片合成一個圖片,而後利用 css 的 background-position 定位顯示不一樣的 icon 圖標。但這個也有一個很大的痛點,維護困難。每新增一個圖標,都須要改動原始圖片,還可能不當心出錯影響到前面定位好的圖片,並且一修改雪碧圖,圖片緩存就失效了,長此以往你不知道該怎麼維護了。css
font 庫
後來漸漸地一個項目裏幾乎不會使用任何本地的圖片了,而使用一些 font 庫來實現頁面圖標。常見的如 Font Awesome ,使用起來也很是的方便,但它有一個致命的缺點就是找起來真的很不方便,每次找一個圖標特別的費眼睛,還有就是它的定製性也很是的不友善,它的圖標庫一共有675個圖標,說少也很多,但仍是會經常出現找不到你所須要圖標的狀況。固然對於沒有啥特別 ui 追求的初創公司來講仍是能忍一忍的。但隨着公司的壯大,來了愈來愈多對前端指手畫腳的人,喪心病狂的設計師,他們會說不!這icon這麼醜,這簡直是在侮辱他們高級設計師的稱號啊!不過好在這時候有了iconfont 。html
iconfont
一個阿里爸爸作的開源圖庫,人家還有專門的 github issue(雖然個人一個 issue 半年多了也沒回應/(ㄒoㄒ)/~~),但人家的圖標數量仍是很驚人的,不只有幾百個公司的開源圖標庫,還有各式各樣的小圖標,還支持自定義建立圖標庫,因此無論你是一家創業公司仍是對設計頗有要求的公司,它都能很好的幫助你解決管理圖標的痛點。你想要的基本都有~前端
最開始咱們使用了unicode
的格式,它主要的特色是
優點vue
劣勢java
使用方法:
第一步:引入自定義字體 `font-facereact
@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的樣式webpack
.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; }
第三步:挑選相應圖標並獲取字體編碼,應用於頁面git
<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 是一個真正的矢量,無論你再怎麼的放縮它都不會失真模糊,並且svg能夠控制的屬性也更加的豐富,也能作出更加生動和複雜的圖標。如今ui設計師平時都喜歡使用 sketch 來工做,只要輕鬆一鍵就能導出 svg 了,因此 svg 也更受設計師的青睞。Inline SVG vs Icon Fonts 這篇文章詳細的比較了 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
生成的。
你徹底不知道哪一個圖標名對應什麼圖標,一臉尼克揚問號??? 每次增刪改圖標只能總體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的項目有所幫助。歡迎使用和提出不足。
樓主我的免費圈子。