icon在咱們前端平常開發中是很經常使用的,它有不少種使用方式,時至今日,它的使用方式通過了不少種演變,本文會爲你們介紹icon的一些歷史演變,分析一下這幾種使用方式的優劣,咱們將採用svg sprites
這種方式使用icon,演示代碼使用vue+vue-cli3+,看完以後,你會發現這種使用方式徹底稱得上優雅二字javascript
最先咱們使用圖標時只是單純img標籤引入圖片,我的感受也還好css
可是這樣網頁上會有不少img圖標的資源請求,這是它最大的缺點html
後來咱們爲了優化資源請求開始使用CSS雪碧圖(css sprites)前端
CSS Sprites在國內不少人叫css精靈/css雪碧圖(啥都行),是一種網頁圖片應用處理方式。它容許你將一個頁面涉及到的全部零星圖片都包含到一張大圖中去,這樣一來,當訪問該頁面時,載入的圖片就不會像之前那樣一幅一幅地慢慢顯示出來了。加速的關鍵,不是下降質量,而是減小個數vue
CSS Sprites其實就是把網頁中一些背景圖片整合到一張圖片文件中,再利用CSS的background-image background- repeat background-position
的組合進行背景定位,background-position
能夠用數字精確的定位出背景圖片的位置java
利用CSS Sprites能很好地減小網頁的http請求,從而大大的提升頁面的性能,這也是CSS Sprites最大的優勢webpack
同時它的缺點也很明顯,CSS Sprites在開發的時候比較麻煩,須要計算基準位置來進行定位,維護的時候每每改動一個圖標咱們就得改整個雪碧圖,一不當心就搞得整個網頁的圖標錯位了git
再到後來就出現了font庫,也就是字體圖標庫,它出現給了咱們開發很大便利,使用起來也很是方便,字體圖標爲何方便,由於咱們能夠直接從市面上的font字體圖標庫裏找圖標,直接使用,還能夠很好的控制一些基礎樣式github
國內估計使用量最大也是最全的圖標庫我以爲就是阿里矢量圖標庫(iconfont)了,各類圖標簡直不要太多,最重要的是開源免費web
拿iconfont來講,它有三種使用方式,分別是unicode,font-class,symbol
,都很是簡單
固然,沒有使用過的小夥伴直接百度搜索關鍵詞iconfont使用,相信看一看就會了
接下來咱們來看下這三種方式的優缺點(官方的):
unicode是字體在網頁端最原始的應用方式,特色是:
注意:新版iconfont支持多色圖標,這些多色圖標在unicode模式下將不能使用,若是有需求建議使用symbol的引用方式
unicode使用步驟以下:
@font-face {font-family: 'iconfont';
src: url('iconfont.eot');
src: url('iconfont.eot?#iefix') format('embedded-opentype'),
url('iconfont.woff') format('woff'),
url('iconfont.ttf') format('truetype'),
url('iconfont.svg#iconfont') format('svg');
}
複製代碼
.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">3</i>
複製代碼
font-class是unicode使用方式的一種變種,主要是解決unicode書寫不直觀,語意不明確的問題。
與unicode使用方式相比,具備以下特色:
使用步驟以下:
//at.alicdn.com/t/font_8d5l8fzk5b87iudi.css
複製代碼
<i class="iconfont icon-xxx"></i>
複製代碼
這是一種全新的使用方式,應該說這纔是將來的主流,也是平臺目前推薦的用法。這種用法實際上是作了一個svg的集合,與上面兩種相比具備以下特色:
font-size
,color
來調整樣式。使用步驟以下:
//at.alicdn.com/t/font_8d5l8fzk5b87iudi.js
複製代碼
<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>
複製代碼
以上三種使用姿式的優缺點相信你們都瞭解了,symbol這中使用方式就是本文的正題了,其實以前我是一直都使用font-class這種方式的(你們估計用這個的也不少),可是它有點麻煩,由於我每次迭代項目時,修改或者添加圖標都要去從新下載一份新的包,還不支持多色圖標,可是如今我覺決定換了它,由於get到了一種更好的方式,它就是symbol
symbol它支持多色圖標,兼容性到ie9+,這也沒什麼,畢竟某e瀏覽器差很少涼透了,瀏覽器渲染svg性能這個也能夠不用擔憂,早在14年張鑫旭的一篇帖子 SVG Sprite介紹 完美詮釋了svg sprite的工做方式,而且對其很看好,或許這就是大佬的眼光吧 - _ -
單純使用iconfont官方那種symbol方式實際上是有點low的,實際開發中咱們能夠結合項目,讓他變得簡單,接下來咱們就要進入本文正題,優雅使用icon了,哈哈哈,碼這麼多字,我太難了
咱們使用vue-cli3搭建項目
怎麼樣纔算優雅,首先咱們在src目錄下新建icons/
文件夾,在icons/
文件夾下建svg/
文件夾,未來咱們項目中的svg圖標都會統一放在這裏
接下來咱們在官網搞來一個svg圖標
點擊svg下載到icons/svg
目錄下修改文件名爲qq.svg
,或者是在icons/svg
目錄下新建一個qq.svg
文件,把複製的svg代碼放進去也能夠
這樣就獲取到了一個圖標,很easy
vue-cli對svg文件有默認的url-loader
處理,咱們要使用svg 圖標需單獨進行配置
下載一個插件svg-sprite-loader
來單獨處理咱們的svg圖標,它是一個webpack loader,支持將多個svg打包成svg sprites
npm下載
npm install svg-sprite-loader -D
複製代碼
yarn下載
yarn add svg-sprite-loader -D
複製代碼
咱們要怎麼使用它呢,首先咱們不能覆蓋原有的svg解析loader,咱們只須要把icons/svg
這個文件夾下的svg文件解析打包便可,咱們在vue.config.js
中chainWebpack函數中配置,來看代碼
// 內置路徑包
const path = require("path");
// 定義resolve方法,獲取絕對路徑
function resolve(dir) {
return path.join(__dirname, dir);
}
module.exports = {
// 一個函數,會接收一個基於 webpack-chain 的 ChainableConfig 實例
// 容許對內部的 webpack 配置進行更細粒度的修改
chainWebpack: config => {
// 配置svg默認規則排除icons目錄中svg文件處理
config.module
.rule("svg")
.exclude.add(resolve("src/icons"))
.end();
// 新增icons規則,設置svg-sprite-loader處理icons目錄中svg文件
config.module
.rule("icons")
.test(/\.svg$/)
.include.add(resolve("src/icons"))
.end()
.use("svg-sprite-loader")
.loader("svg-sprite-loader")
.options({ symbolId: "icon-[name]" })
.end();
}
}
複製代碼
若是咱們不清楚cli的默認配置,怕改錯,可經過vue inspect審查webpack內部配置,詳細請看: inspect使用
上面代碼中咱們使用了webpack的鏈式高級用法來處理loader,首先排除了默認svg的loader對咱們icons/
目錄下svg文件的處理,而後新增了一個規則讓svg-sprite-loader
處理咱們icons/
文件夾下的svg文件,最後咱們設置了icon-
加上通過處理的svg文件名做爲symbolId,也就是說咱們在使用qq.svg
時能夠直接在use標籤使用#icon-qq
,關於鏈式操做不了解的小夥伴能夠看: 鏈式操做(高級)
代碼中咱們引入了path
這樣一個內置的包,定義了一個resolve
方法,該方法主要是來獲取文件絕對路徑的,咱們把使用路徑的地方都使用該方法轉爲絕對路徑,固然使用相對路徑也是能夠的,可是不太安全,平臺解析相對路徑有差別性,因此絕對路徑是最安全的
如今咱們就能夠在你想使用圖標的位置使用了,使用方式以下
在main.js
中引入(全局引入)要使用的圖標文件
import "@/icons/svg/qq.svg";
複製代碼
模版中使用
<svg>
<use xlink:href="#icon-qq"></use>
</svg>
複製代碼
你覺得這就完了?不,還遠遠不夠,這樣使用一個圖標就得引入文件一次也太麻煩了,接着看下文
知道爲何在icons/
文件夾下還有一個存放svg文件的svg/
文件夾嗎,就是爲了這一步自動化引入準備的,咱們在icons/
文件夾下新建index.js
文件,兩行代碼搞定,內容以下
// icons圖標自動加載
const req = require.context("./svg", false, /\.svg$/);
req.keys().map(req);
複製代碼
上面代碼中咱們使用require.context
設置了當前目錄下的./svg
文件爲上下文,使用正則匹配了它須要檢測的文件名,這樣它就會在當前目錄的svg文件夾下去匹配符合規則的文件名
而後咱們使用req.keys
拿到全部文件名數組,再使用map遍歷加載req方法,這樣當該文件被調用時會遍歷加載全部匹配到的文件,這就很nice了
看看咱們改進後的使用方法:
註釋掉以前的代碼,在main.js
中引入icons/index.js
文件
import "@/icons/index.js";
複製代碼
模板中使用和上面同樣,不過此次改進當咱們再次下載了一個svg圖標時,不用再引入一遍圖標svg了,由於咱們作了自動化,icons/svg/
下的svg後綴圖標文件均可被自動引入
<svg>
<use xlink:href="#icon-qq"></use>
</svg>
<svg>
<use xlink:href="#icon-wx"></use>
</svg>
...
複製代碼
是否是很方便,你覺得結束了?不,咱們還能夠再簡化,由於每次使用都得svg標籤包着use太麻煩了,寫着也不太雅觀,咱們繼續簡化,必定要看起來使用起來都十分優雅
在components/
目錄下新建SvgIcon/index.vue
文件,咱們寫一個svgicon組件,封裝一下再全局註冊,這樣使用起來就會很方便了!
svg-icon組件代碼以下:
<template>
<svg :class="svgClass" aria-hidden="true" v-on="$listeners">
<use :xlink:href="iconName" />
</svg>
</template>
<script> export default { name: "SvgIcon", props: { iconClass: { type: String, required: true }, className: { type: String, default: "" } }, computed: { iconName() { return `#icon-${this.iconClass}`; }, svgClass() { if (this.className) { return "svg-icon " + this.className; } else { return "svg-icon"; } } } }; </script>
<style scoped> .svg-icon { width: 1em; height: 1em; vertical-align: -0.15em; fill: currentColor; overflow: hidden; } </style>
複製代碼
固然組件內部咱們還能夠根據自身項目狀況進行擴展,我這邊寫了基礎的配置
組件寫好了以後咱們在icons/index.js
中進行全局註冊,這樣咱們只引入這一個文件就能夠達到自動加載和組件註冊兩個功能
icons/index.js
改進以下:
import Vue from "vue";
import SvgIcon from "@/components/SvgIcon";
// icons圖標自動加載
const req = require.context("./svg", false, /\.svg$/);
req.keys().map(req);
// 全局註冊svg-icon組件
Vue.component("svg-icon", SvgIcon);
複製代碼
最後就是咱們的使用了,在main.js
文件引入icons/index.js
import "@/icons/index.js";
複製代碼
再來看看咱們使用圖標的方法,組件中:
<template>
<svg-icon icon-class="qq" class-name="qq-style"></svg-icon>
</template>
複製代碼
看,咱們只用在icon-class
中傳入要使用的圖標文件名就能夠了,固然class-name
還能夠傳入一個類,進行一些簡單的樣式修改,是否是很優雅,你get到了嗎?
碼字不易,動動小手,給個關注,點個贊啥的,哈哈
已儘可能通俗解釋,保證無錯,奈何水平有限,歡迎指錯
做者:isboyjc
郵箱:214930661@qq.com
GitHub: github.com/isboyjc
參考文章: