引言:最近開始寫vue的項目,借鑒了一下vue-element-admin源碼,針對vue有一個關於icon圖標的處理,最近也找了很多關於vue的icon處理的解決方案,大部分都是按照之前小程序的方式直接引入iconfont項目,然后在外面封裝調用樣式就可以了。
- 按照平時導入icon的方法的話有一些已知的缺點
- 操作繁瑣,每次ui需要加一些新的圖標的時候,都要重新下載圖標庫的項目,然后把整體的文件(其中包括css,svg,ttf,woff等)替換掉。
- 如果更改名稱的話,需要在圖標庫里改一次,然后進行下載復制拷貝。
- iconfont網站庫圖標內容有限,特殊業務條件需要uimm們自己設計的圖(PSD小圖標變身SVG Sprites/font-face歷險記)
- 文檔中推薦的方式是引入svg
使用svg的優點
- 圖標易於實時修改
- 圖標可以帶動畫
- 可以使用標磚的prop和默認值來將圖標保持在一個典型的尺寸並隨時按需改變他們
- 圖標是內聯的,所以不需要額外的HTTP請求
- 可以動態地使得圖標可訪問
- 這里准備采用文檔中推薦的插件svg-sprite-loader進行介紹
注: 用來根據導入的svg文件自動生成symbol標簽並插入html,接下來就可以在模板忠方便地使用svg-sprite技術了
使用svg-sprite的好處
- 頁面代碼清爽
- 可使用ID隨處重復調用
- 每個SVG圖標都可以更改大小顏色
安裝插件
npm install svg-sprite-loader --save
webpack配置
在webpack.base.conf.js加入處理svg的loader
{
test: /\.svg$/,
loader: 'svg-sprite-loader',
include: [resolve('src/icons')],
options: {
symbolId: 'icon-[name]'
}
}
這個配置默認導入src文件下的icons文件
src/icons/index
// requires and returns all modules that match
const requireAll = requireContext => requireContext.keys().map(requireContext);
// import all svg
const req = require.context('./assets/svg', true, /\.svg$/);
requireAll(req);
然后運行
npm run dev
報錯了,此時我們看我們的webpack配置
{
test: /\.svg$/,
loader: 'svg-sprite-loader',
include: path.resolve(__dirname, '../src/assets/icons')
},
{
test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
loader: 'url-loader',
options: {
limit: 10000,
name: utils.assetsPath('img/[name].[hash:7].[ext]')
}
},
下面url-loader中也處理了svg文件,刪掉svg處理之后就顯示我們需要的svg了,但是之前的url是我們element-ui里生成的,需要加上**symbol**,不去處理src/assets/svgs路徑下的svg文件
{
test: /\.svg$/,
loader: 'svg-sprite-loader',
include: path.resolve(__dirname, '../src/assets/icons')
},
{
test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
loader: 'url-loader',
exclude: [
path.resolve(__dirname, '../src/assets/icons'),
],
options: {
limit: 10000,
name: utils.assetsPath('img/[name].[hash:7].[ext]')
}
},
注:require.context,webpack管理依賴
使用方法
<svg>
<use xlink:href="#jisuan" />
</svg>
import '@/assets/icons/jisuan.svg'
組件化
當然,這並不是最后想要的結果,我們需要將每個svg文件整合起來組件化,這樣方便以后的調用
建立一個Icon.vue文件
<template>
<svg>
<use :xlink:href="`#${name}`"></use>
</svg>
</template>
<script>
export default {
name: 'icon',
props: {
name: {
type: String,
required: true,
},
},
}
</script>
<icon name="jisuan" />
import '@/assets/icons/jisuan.svg'
自動導入
這里插入每個svg圖標都需要import,在我們平時寫項目的時候js,vue文件都已經實現了自動導入,這里照葫蘆畫瓢,讓src/assets/svg里的文件自動導入
assets/icon/scan.js
const requireAll = requireContext => requireContext.keys().map(requireContext);
// import all svg
const req = require.context('./assets/svg', true, /\.svg$/);
requireAll(req);
main.js
import './assets/scan.js'
參考文檔: