Vue3+Element?Plus使用svg加載iconfont的處理方法
安裝依賴
由于我們是Vue3項(xiàng)目,可以使用vite
來(lái)快速創(chuàng)建一個(gè)Vu3項(xiàng)目:
npm install -g yarn yarn create vite my-vue-app --template vue // 這里我們使用vue模板,默認(rèn)是Javascript語(yǔ)法,如果需要ts語(yǔ)法則需要指定模板為vue-ts cd my-vue-app yarn yarn dev
創(chuàng)建好項(xiàng)目后,我們?cè)賮?lái)引入Element Plus
,安裝并引入的過(guò)程如下:
安裝
:
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使用的類名有很大的不同,也就是說(shuō)我們無(wú)法直接在el-icon
中使用iconfont
的圖標(biāo)。雖然Element Plus的圖標(biāo)已經(jīng)能滿足大部分場(chǎng)景的需求,但是一些特殊場(chǎng)景只能從iconfont
或者自定義的圖標(biāo)上獲取。
那么有沒(méi)有辦法將iconfont
封裝成svg,并給el-icon
調(diào)用呢?
將iconfont封裝成svg
可縮放矢量圖形(Scalable Vector Graphics),簡(jiǎn)稱SVG,是一種基于XML的,可用于描述二維的矢量圖形。SVG可以優(yōu)雅而簡(jiǎn)潔的渲染不同大小的圖形,并且可以被無(wú)限縮放并且保持不失真或者降低質(zhì)量,這一特性比JPEG
、PNG
等好用太多。SVG的內(nèi)容相當(dāng)多,感興趣的可以去MDN上查看文檔:SVG。我們這里只是簡(jiǎn)單實(shí)用SVG來(lái)封裝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來(lái)調(diào)用了,這里我們重點(diǎn)說(shuō)幾個(gè)屬性:
- aria-hidden:默認(rèn)為false,設(shè)置為true表示會(huì)把整個(gè)元素包括子元素從可訪問(wèn)樹(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>
按理說(shuō)到這里,本篇教程就應(yīng)該結(jié)束了。但是,在使用的過(guò)程中,按照正常的方式設(shè)置的hover
樣式不生效,筆者嘗試了幾種方案,最終放棄hover
,采用監(jiān)聽(tīng)鼠標(biāo)事件的方式解決。
設(shè)置”hover“樣式
SVG不同于class
樣式,其無(wú)法直接通過(guò)修改hover
樣式來(lái)設(shè)置鼠標(biāo)懸浮在圖標(biāo)上面時(shí)顏色改變,這個(gè)時(shí)候我們就需要換一種思路了。我們?cè)?code>SvgIcon.vue中傳入了color
,并且通過(guò)fill
將color
作用到SVG上,因此我們可以在父組件中修改color
的值來(lái)實(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ì)比來(lái)看,其實(shí)也不復(fù)雜。
為什么圖標(biāo)顏色無(wú)法修改?
可能有點(diǎn)朋友按照上述的步驟操作后,發(fā)現(xiàn)并不能修改圖標(biāo)顏色,如果不是代碼有誤,那應(yīng)該就是導(dǎo)入的iconfont有問(wèn)題。一般我們會(huì)直接在iconfont官網(wǎng)下載圖標(biāo):
將下載好的壓縮包解壓后,只復(fù)制iconfont.js
到項(xiàng)目中即可:
// main.js ... import '@/assets/iconfont/iconfont.js';
我們來(lái)看一下iconfont.js
中icon-close1
和icon-close
的源碼:
可以發(fā)現(xiàn),這兩個(gè)圖標(biāo)最大的差別就是一個(gè)有fill
,另一個(gè)沒(méi)有,而這就是問(wèn)題的關(guān)鍵。如果某一個(gè)圖標(biāo)的fill不為空,那么作為svg引用時(shí)將無(wú)法修改填充色。
舉個(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è)問(wèn)題應(yīng)該怎么解決呢,一種方式就是手動(dòng)刪除所有Icon的fill
屬性,另一個(gè)就是在iconfont上面使用批量去色。
批量去色后,我們?cè)俅蜗螺d圖標(biāo),并解壓后替換掉原來(lái)的iconfont.js
,再去源碼看看就會(huì)發(fā)現(xiàn)所有圖標(biāo)的fill
都沒(méi)有了,而且也可以修改顏色。
總結(jié)
本文詳細(xì)介紹了如何在Element Plus中使用iconfont,簡(jiǎn)單的說(shuō)就是要將其封裝成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-06vue如何點(diǎn)擊多個(gè)tab標(biāo)簽打開關(guān)閉多個(gè)頁(yè)面
這篇文章主要介紹了vue如何點(diǎn)擊多個(gè)tab標(biāo)簽打開關(guān)閉多個(gè)頁(yè)面,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-09-09vue數(shù)組對(duì)象排序的實(shí)現(xiàn)代碼
這篇文章主要介紹了vue數(shù)組對(duì)象排序的實(shí)現(xiàn)代碼,這里整理了詳細(xì)的代碼,非常具有實(shí)用價(jià)值,需要的朋友可以參考下2018-06-06webpack轉(zhuǎn)vite的詳細(xì)操作流程與問(wèn)題總結(jié)
Vite是新一代的前端開發(fā)與構(gòu)建工具,相比于傳統(tǒng)的webpack,Vite 有著極速的本地項(xiàng)目啟動(dòng)速度(通常不超過(guò)5s)以及極速的熱更新速度(幾乎無(wú)感知),下面這篇文章主要給大家介紹了關(guān)于webpack轉(zhuǎn)vite的詳細(xì)操作流程與問(wèn)題總結(jié)的相關(guān)資料,需要的朋友可以參考下2023-03-03Vue3中同時(shí)定義多個(gè)插槽的實(shí)現(xiàn)示例
本文主要介紹了Vue3中同時(shí)定義多個(gè)插槽的實(shí)現(xiàn)示例,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2023-12-12如何解決element-ui動(dòng)態(tài)加載級(jí)聯(lián)選擇器默認(rèn)選中問(wèn)題
這篇文章主要介紹了如何解決element-ui動(dòng)態(tài)加載級(jí)聯(lián)選擇器默認(rèn)選中問(wèn)題,文章圍繞主題展開詳細(xì)的內(nèi)容介紹,具有一定的參考價(jià)值,需要的朋友可以參考一下2022-09-09深入解析Vue源碼實(shí)例掛載與編譯流程實(shí)現(xiàn)思路詳解
這篇文章主要介紹了Vue源碼實(shí)例掛載與編譯流程實(shí)現(xiàn)思路詳解,非常不錯(cuò),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2019-05-05