關鍵字:BuildAdmin、Icon、圖標、Vue、ElementUI
前言
說到圖標,在BuildAdmin中用到的地方很多。比如上一篇中的折疊圖標,還有菜單欄圖標、導航菜單欄圖標等。常見的圖標有:ElementUI圖標、font-awesome、iconfont阿里圖標以及本地svg這四類圖標。
在使用四種不同的圖標時,使用的標簽都是不一樣的,所以定義一個統一的組件,使用一個標簽就能包含四類圖標是非常有必要的。當然,這只是其中的一個原因,至于其他原因可以接著看下文。
這里先放出架構圖,可以看完整篇文章之后再回來看。
圖標icon
BuildAdmin在aside中主要使用了兩種圖標:
1. 菜單圖標
用的是官方 @element-plus/icons-vue 。
圖標庫鏈接:https://element-plus.org/zh-CN/component/icon.html
2. 折疊按鈕
用的是font-awesome圖標庫,使用npm安裝后即可使用。
npm i font-awesome
圖標使用
BuildAdmin中,封裝了一個Icon組件,作為定義圖標的組件。
后來會重點分析代碼,這里先思考:為什么要為圖標單獨封裝一個組件? 這里先看看兩種圖標的用法。
<!-- 定義icons-vue圖標 -->
<el-icon :size="size" :color="color"><Edit />
</el-icon><!-- 定義font-awesome圖標 -->
<i class="fa fa-camera-retro fa-lg"></i>
首先,兩種圖標的寫法不一致。其次,如果說是遍歷菜單路由的時候,如何確認el-icon要使用哪個圖標? 這一點主要在動態路由會講,這里先簡單的提一下。
什么意思呢?就是你從后端請求了菜單列表,控制臺菜單要用圖標A,會員中心菜單要用圖標B,你該如何用el-icon渲染這些圖標標簽呢?從上面的代碼示例可以看到,你只有把Edit替換成A和B才會顯示A/B圖標,但是在代碼里想要替換,難度還是挺大的。
所以這個時候就需要定義一個類似于方法的東西,設置一個圖標參數,根據圖標參返回一個現成的圖標。這個Icon組件就相當于這個”方法“,會根據你傳入的A、B來返回對應的圖標。
封裝ElementPlus圖標
逐個分析實現原理,這里先從ElementPlus圖標開始。
1. Icon的使用
先回顧一下封裝好的Icon是如何使用的。
<Iconv-if="config.layout.layoutMode != 'Streamline'"@click="onMenuCollapse":name="config.layout.menuCollapse ? 'fa fa-indent' : 'fa fa-dedent'":class="config.layout.menuCollapse ? 'unfold' : ''":color="config.getColorVal('menuActiveColor')"size="18"class="fold"
/>
v-if、click這些可以先不用管,這些都是邏輯、事件的屬性。這里主要關注name、class、size、color這些基本屬性標簽。
這里說一下,上面的config就是上一篇提到的pinia定義的狀態變量config.ts。
2.定義Icon
使用 defineComponent 定義Icon組件,在TypeScript中必須使用這個方法定義。使用props接收Icon組件的參數(vue中的props和emits一定要好好學,都是父子組件之間傳遞參數的)。
這純純的是vue選項式寫法。name表示這個組件是Icon,props里面定義的是傳入參數,這里是name、size、color。type表示類型,required表示是否必須,defalut表示默認值。在Icon使用示例中,三個屬性都定義了。
在setup()中對接收到的參數進行一個預處理,主要是給size加上px單位。接下來,就是如何根據這些參數來渲染對應的圖標。
3. 渲染對應圖標
這里可以看到,如果name是以el-icon開頭,就渲染一個Element Plus的圖標,如果是fa開頭,就渲染font-awesome的圖標。h() 就是vue的渲染函數,相當于createVnode()。
h()的用法在官網里面有,至于如何確定里面的class、style參數,同樣可以從控制臺里面看。
可以看到font-awesome的圖標,在編譯之后就是一個i元素,我們在使用Icon時,傳入的參數name為fa fa-indent,根據瀏覽器中渲染后的i標簽的class,只需要再拼接上icon和空格就可以。
這就是反向學習,從應用結果中來推斷一個知識點的用法。
3.Element Plus圖標注冊
和font-awesome不同的是,Element的el-icon是組件,需要先加載然后才能使用。根據官方文檔將每個icon組件注冊,只不過在注冊時,在icon的name之前統一加上el-icon前綴,這樣便于在Icon中識別。
定義了一個 registerIcons() 方法來注冊Icon。其中,app是全局的根節點,調用component() 來加載Icon,然后遍歷Element中所有的標簽進行注冊加載。
同樣,可以在瀏覽器查看el-icon在h()中渲染的class和style。
4. 加載Icon
最后,在main.ts中調用registerIcons完成加載。
import {registerIcons} from '@/utils/icons'const app = createApp(App)
registerIcons(app)
這樣,我們就可以使用<Icon>標簽以及el-icon標簽。
結語
本篇文章主要寫了Icon圖標的注冊,Icon作為一個“門面”,為使用多種類型的圖標提供了統一的規范。在BuildAadmin的Icon實現中,對本地svg圖標加載也進行了實現。
我本來覺得svg用不到,就在Icon中只實現了el-icon和front-awesome兩種圖標,后來在實現導航欄時又回過頭來,實現了svg圖標,這個就留給下篇文章。