Vue3+Element?Plus使用svg加載iconfont的處理方法
安裝依賴
由于我們是Vue3項(xiàng)目,可以使用vite來快速創(chuàng)建一個(gè)Vu3項(xiàng)目:
npm install -g yarn yarn create vite my-vue-app --template vue // 這里我們使用vue模板,默認(rèn)是Javascript語法,如果需要ts語法則需要指定模板為vue-ts cd my-vue-app yarn yarn dev
創(chuàng)建好項(xiàng)目后,我們?cè)賮硪?code>Element Plus,安裝并引入的過程如下:
安裝:
yarn add element-plus
完整引入:
// main.js ... import ElementPlus from 'element-plus' import 'element-plus/dist/index.css' app.use(ElementPlus)
引入后,我們就可以在Vue3項(xiàng)目中使用了:
<template><el-button>按鈕</el-button> </template>
Element Plus使用Icon會(huì)比Element UI稍微麻煩點(diǎn)。首先我們需要安裝Icon的依賴:
yarn add @element-plus/icons-vue
我們?cè)?code>main.js中注冊(cè)所有的圖標(biāo),當(dāng)然也可以按需引入圖標(biāo):
// main.js
// 全局引入
import * as ElementPlusIconsVue from '@element-plus/icons-vue'
...
for (const [key, component] of Object.entries(ElementPlusIconsVue)) {app.component(key, component)
}
el-icon的使用:
<template><el-icon><Edit /></el-icon>
</template>
<script setup> // import {Edit} from '@element-plus/icons-vue' // 按需引入,如果已經(jīng)全局引入了就不需要按需引入 </script>
Element Plus的el-icon使用的是svg,這與Element UI使用的類名有很大的不同,也就是說我們無法直接在el-icon中使用iconfont的圖標(biāo)。雖然Element Plus的圖標(biāo)已經(jīng)能滿足大部分場(chǎng)景的需求,但是一些特殊場(chǎng)景只能從iconfont或者自定義的圖標(biāo)上獲取。
那么有沒有辦法將iconfont封裝成svg,并給el-icon調(diào)用呢?
將iconfont封裝成svg
可縮放矢量圖形(Scalable Vector Graphics),簡(jiǎn)稱SVG,是一種基于XML的,可用于描述二維的矢量圖形。SVG可以優(yōu)雅而簡(jiǎn)潔的渲染不同大小的圖形,并且可以被無限縮放并且保持不失真或者降低質(zhì)量,這一特性比JPEG、PNG等好用太多。SVG的內(nèi)容相當(dāng)多,感興趣的可以去MDN上查看文檔:SVG。我們這里只是簡(jiǎn)單實(shí)用SVG來封裝iconfont。
首先我們新建一個(gè)SvgIcon.vue的文件,
<template><svg :class="classList" aria-hidden="true">
<use :xlink:href="iconName" rel="external nofollow" :fill="color" /></svg>
</template>
<script setup> import { computed } from 'vue';
const props = defineProps({className: {
type: String,
default: ''},iconClass: {
type: String,
required: true},color: {
type: String,
default: '#409eff'},size: {
type: String,
default: '20px'}
})
const classList = computed(() => {return ['icon', props.className || '']
})
const iconName = computed(() => {return `#${props.iconClass}`
}) </script>
<style scoped> .icon {/* v-bind是Vue3才支持的功能,可以將CSS的值與js的值綁定 */width: v-bind('props.size');height: v-bind('props.size');position: relative;vertical-align: -2px;fill: currentColor;
} </style> 這樣就將iconfont封裝成了svg來調(diào)用了,這里我們重點(diǎn)說幾個(gè)屬性:
- aria-hidden:默認(rèn)為false,設(shè)置為true表示會(huì)把整個(gè)元素包括子元素從可訪問樹(AOM)上移除,但是在DOM樹上還是存在的
- xlink:href:use元素的屬性
- v-bind:Vue3的特性,可用于關(guān)聯(lián)CSS和js
- fill:如果在動(dòng)畫接收還需要保持動(dòng)畫的值,可用于設(shè)置顏色
如何使用
使用已經(jīng)封裝好的SvgIcon.vue比較簡(jiǎn)單,就和正常的組件一樣使用即可。例如:
<template><SvgIcon :icon-class="icon-pointer"></SvgIcon> </template> <script setup> import SvgIcon from './SvgIcon.vue' </sript>
如果不想在局部注冊(cè)組件,也可以注冊(cè)為全局組件:
// main.js
import SvgIcon from '@/SvgIcon.vue'
...
app.component('SvgIcon', SvgIcon);
作為SVG組件,我們也可以直接使用在el-icon中,這樣就可以添加任意iconfont到el-icon中了:
<template><el-icon><SvgIcon :icon-class="icon-pointer"></SvgIcon></el-icon> </template>
按理說到這里,本篇教程就應(yīng)該結(jié)束了。但是,在使用的過程中,按照正常的方式設(shè)置的hover樣式不生效,筆者嘗試了幾種方案,最終放棄hover,采用監(jiān)聽鼠標(biāo)事件的方式解決。
設(shè)置”hover“樣式
SVG不同于class樣式,其無法直接通過修改hover樣式來設(shè)置鼠標(biāo)懸浮在圖標(biāo)上面時(shí)顏色改變,這個(gè)時(shí)候我們就需要換一種思路了。我們?cè)?code>SvgIcon.vue中傳入了color,并且通過fill將color作用到SVG上,因此我們可以在父組件中修改color的值來實(shí)現(xiàn)"hover"效果。
<template><div @mouseenter="() => handleMouseenter" @mouseleave="() => handleMouseleave"><SvgIcon :icon-class="icon-pointer" :color="color"></SvgIcon></div>
</template>
<script setup> import {ref} from 'vue'
const color = ref('red')
const handleMouseenter = () => {color.value = 'blue'
}
const handleMouseleave = () => {color.value = 'red'
}
</sript>
上面的例子中適用于單個(gè)SvgIcon,如果是多個(gè)的話,就需要進(jìn)一步改造了:
<template><div v-for="(item, index) in list" @mouseenter="($event) => handleMouseenter($event, index)" @mouseleave="($event) => handleMouseleave($event, index)"><SvgIcon :icon-class="icon-pointer" :color="hoverIconIndex == index ? 'blue' : 'red'"></SvgIcon></div>
</template>
<script setup> import {ref} from 'vue'
const list = ref([{name: '張三'}
])
const color = ref('red')
const hoverIconIndex = ref(-1)
const handleMouseenter = (event, index) => {hoverIconIndex.value = index;
}
const handleMouseleave = (event, index) => {hoverIconIndex.value = -1;
}
</sript>
對(duì)比來看,其實(shí)也不復(fù)雜。
為什么圖標(biāo)顏色無法修改?
可能有點(diǎn)朋友按照上述的步驟操作后,發(fā)現(xiàn)并不能修改圖標(biāo)顏色,如果不是代碼有誤,那應(yīng)該就是導(dǎo)入的iconfont有問題。一般我們會(huì)直接在iconfont官網(wǎng)下載圖標(biāo):

將下載好的壓縮包解壓后,只復(fù)制iconfont.js到項(xiàng)目中即可:
// main.js ... import '@/assets/iconfont/iconfont.js';
我們來看一下iconfont.js中icon-close1和icon-close的源碼:

可以發(fā)現(xiàn),這兩個(gè)圖標(biāo)最大的差別就是一個(gè)有fill,另一個(gè)沒有,而這就是問題的關(guān)鍵。如果某一個(gè)圖標(biāo)的fill不為空,那么作為svg引用時(shí)將無法修改填充色。
舉個(gè)例子:
<template><div>
<SvgIcon :color="'red'" :icon-class="'icon-close'"></SvgIcon>
<SvgIcon :color="'red'" :icon-class="'icon-close1'"></SvgIcon>
</div>
</template>
運(yùn)行結(jié)果:

遇到這個(gè)問題應(yīng)該怎么解決呢,一種方式就是手動(dòng)刪除所有Icon的fill屬性,另一個(gè)就是在iconfont上面使用批量去色。

批量去色后,我們?cè)俅蜗螺d圖標(biāo),并解壓后替換掉原來的iconfont.js,再去源碼看看就會(huì)發(fā)現(xiàn)所有圖標(biāo)的fill都沒有了,而且也可以修改顏色。
總結(jié)
本文詳細(xì)介紹了如何在Element Plus中使用iconfont,簡(jiǎn)單的說就是要將其封裝成SVG,并且支持動(dòng)態(tài)修改顏色。雖然操作上不難,但是容易踩一些坑,你學(xué)會(huì)了嗎?
相關(guān)文章
vue-cli對(duì)element-ui組件進(jìn)行二次封裝的實(shí)戰(zhàn)記錄
組件類似于需要多個(gè)地方用到的方法,在Vue中組件就是一種復(fù)用(經(jīng)常使用)一個(gè)功能的手段,下面這篇文章主要給大家介紹了關(guān)于Vue?element?ui二次封裝的相關(guān)資料,需要的朋友可以參考下2022-06-06
vue如何點(diǎn)擊多個(gè)tab標(biāo)簽打開關(guān)閉多個(gè)頁面
這篇文章主要介紹了vue如何點(diǎn)擊多個(gè)tab標(biāo)簽打開關(guān)閉多個(gè)頁面,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-09-09
vue數(shù)組對(duì)象排序的實(shí)現(xiàn)代碼
這篇文章主要介紹了vue數(shù)組對(duì)象排序的實(shí)現(xiàn)代碼,這里整理了詳細(xì)的代碼,非常具有實(shí)用價(jià)值,需要的朋友可以參考下2018-06-06
webpack轉(zhuǎn)vite的詳細(xì)操作流程與問題總結(jié)
Vite是新一代的前端開發(fā)與構(gòu)建工具,相比于傳統(tǒng)的webpack,Vite 有著極速的本地項(xiàng)目啟動(dòng)速度(通常不超過5s)以及極速的熱更新速度(幾乎無感知),下面這篇文章主要給大家介紹了關(guān)于webpack轉(zhuǎn)vite的詳細(xì)操作流程與問題總結(jié)的相關(guān)資料,需要的朋友可以參考下2023-03-03
Vue3中同時(shí)定義多個(gè)插槽的實(shí)現(xiàn)示例
本文主要介紹了Vue3中同時(shí)定義多個(gè)插槽的實(shí)現(xiàn)示例,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2023-12-12
如何解決element-ui動(dòng)態(tài)加載級(jí)聯(lián)選擇器默認(rèn)選中問題
這篇文章主要介紹了如何解決element-ui動(dòng)態(tài)加載級(jí)聯(lián)選擇器默認(rèn)選中問題,文章圍繞主題展開詳細(xì)的內(nèi)容介紹,具有一定的參考價(jià)值,需要的朋友可以參考一下2022-09-09
深入解析Vue源碼實(shí)例掛載與編譯流程實(shí)現(xiàn)思路詳解
這篇文章主要介紹了Vue源碼實(shí)例掛載與編譯流程實(shí)現(xiàn)思路詳解,非常不錯(cuò),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2019-05-05

