在 Vue 中編寫 SVG 圖標(biāo)組件的方法
在考慮了將矢量圖標(biāo)從圖標(biāo)字體遷移到內(nèi)聯(lián) SVG 的 原因 之后,我在 Vue.js 中找到了一個用 SVG 替換圖標(biāo)字體的解決方案,同時仍能保持使用圖標(biāo)字體的靈活性和易用性——能夠使用 CSS 輕松改變圖標(biāo)的大小、顏色以及其它屬性。
一種流行的方法是使用 v-html 指令和 npm 模塊 html-loader 來將 SVG 導(dǎo)入到我們的 Vue 模板中,并在 Vue 的生命周期函數(shù) mounted() 中修改渲染的 <svg> 元素。CSS 樣式可以直接應(yīng)用到 <svg> 元素或者是其父元素上,并且這些能夠組成一個可復(fù)用的組件。
創(chuàng)建 Svg-icon 組件
讓我們創(chuàng)建 Svg-icon.vue 組件文件,并在里面接收三個 prop 變量。
- icon 是一個字符串類型的 prop 變量用來傳遞 .svg 文件名的導(dǎo)入
- hasFill 是一個布爾類型的 prop 變量來告訴組件 fill 屬性是否用于更改 <svg> 元素的顏色,默認(rèn)值為 false 即不使用 fill 屬性
- growByHeight 是一個布爾類型的 prop 變量來決定 height 或 width 是否相對于 font-size 進(jìn)行縮放,默認(rèn)值為 true 即使用 height
<script> function recursivelyRemoveFill(el) { if (!el) { return; } el.removeAttribute('fill'); [].forEach.call(el.children, child => { recursivelyRemoveFill(child); }); } export default { name: 'svg-icon', props: { icon: { type: String, default: null }, hasFill: { type: Boolean, default: false }, growByHeight: { type: Boolean, default: true }, }, mounted() { if (this.$el.firstElementChild.nodeName === 'svg') { const svgElement = this.$el.firstElementChild; const widthToHeight = (svgElement.clientWidth / svgElement.clientHeight).toFixed(2); if (this.hasFill) { // recursively remove all fill attribute of element and its nested children recursivelyRemoveFill(svgElement); } // set width and height relative to font size // if growByHeight is true, height set to 1em else width set to 1em and remaining is calculated based on widthToHeight ratio if (this.growByHeight) { svgElement.setAttribute('height', '1em'); svgElement.setAttribute('width', `${widthToHeight}em`); } else { svgElement.setAttribute('width', '1em'); svgElement.setAttribute('height', `${1 / widthToHeight}em`); } svgElement.classList.add('svg-class'); } } } </script> <template> <div v-html="require(`html-loader!../assets/svg/${icon}.svg`)" class="svg-container"></div> </template> <style lang="scss" scoped> .svg-container { display: inline-flex; } .svg-class { vertical-align: middle; } </style>
我們將 .svg 圖標(biāo)文件通過 require() 傳遞給 html-loader 方法,該方法會將文件字符串化,并且通過 v-html 指令將其渲染為 <svg> 元素。
所有對 <svg> 元素修改的地方都在 mounted() 生命周期方法里面。
- 將由 growByHeight 定義的 <svg> 元素的 height 或 width 屬性設(shè)置為 1em ( font-size 的一倍)并對另一個元素使用 widthToHeight 。由于并非所有的 SVG 都是正方形的,因此我們從渲染的元素計算 withToHeight 比率,以便 SVG 在父元素的 font-size 屬性大小改變的時候按比例縮放到其原始尺寸。
- 為了設(shè)置 <svg> 元素的 fill 屬性,我們需要覆蓋掉 SVG 文件內(nèi)部附帶的 fill 屬性。當(dāng) hasFill 值為 true 的時候,我們從 <svg> 元素及其子元素中遞歸地刪除 fill 屬性。然后使用 CSS 選擇器將 fill 值添加到其父元素或 <svg> 元素就可以了。
- 還可以向元素中添加例如 class 等其它 DOM 屬性,這些屬性可用于設(shè)置組件中的范圍樣式
創(chuàng)建微笑圖標(biāo)
讓我們使用 Font Awesome 和我們的 Svg-icon 組件中的圖標(biāo)字體創(chuàng)建一個微笑圖標(biāo)。
使用圖標(biāo)字體
<template> <i class="fas fa-smile smile-icon"></i> </template> <style lang="scss" scoped> .smile-icon { font-size: 24px; color: #aaa; &:hover { color: #666; } } </style>
.smile-icon 類的 CSS 選擇器以及偽類選擇器 :hover 來設(shè)置圖標(biāo)的 font-size 和 color 屬性。
使用 Svg-icon 組件
<script> import SvgIcon from './components/Svg-icon'; export default { name: 'my-component', components: { 'svg-icon': SvgIcon, }, } </script> <template> <div class="smile-icon"> <svg-icon icon="smile-solid" :hasFill="true"></svg-icon> </div> </template> <style lang="scss" scoped> .smile-icon { font-size: 24px; fill: #aaa; &:hover { fill: #666; } } </style>
上面的實現(xiàn)和圖標(biāo)字體方法相同,除了 .smile-icon 類在父元素中,在 Svg-icon 組件中, color 屬性被替換為 fill 。我們還必須確保 smile-solid.svg 文件位于 Svg-icon 組件的 require() 方法指定的路徑( ./assets/svg/ )中。
渲染成 HTML
這是由 v-html 的輸出渲染的 HTML。注意:會刪除掉所有的 fill 屬性,并將 height 和 width 屬性添加到 <svg> 中。
<div class="smile-icon"> <svg height="1em" width="1em" aria-hidden="true" focusable="false" data-prefix="fas" data-icon="smile" class="svg-inline--fa fa-smile fa-w-16" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 496 512"> <path d="M248 8C111 8 0 119 0 256s111 248 248 248 248-111 248-248S385 8 248 8zm80 168c17.7 0 32 14.3 32 32s-14.3 32-32 32-32-14.3-32-32 14.3-32 32-32zm-160 0c17.7 0 32 14.3 32 32s-14.3 32-32 32-32-14.3-32-32 14.3-32 32-32zm194.8 170.2C334.3 380.4 292.5 400 248 400s-86.3-19.6-114.8-53.8c-13.6-16.3 11-36.7 24.6-20.5 22.4 26.9 55.2 42.2 90.2 42.2s67.8-15.4 90.2-42.2c13.4-16.2 38.1 4.2 24.6 20.5z"> </path> </svg> </div>
過渡到 SVG
由于 SVG 被認(rèn)為是未來的發(fā)展方向,因此最好是在保留圖標(biāo)字體的易用性的基礎(chǔ)上,逐步放棄使用圖標(biāo)字體。 Svg-icon 組件是一個例子,告訴了我們?nèi)绾问褂每捎玫膸靵沓殡x出 <svg> 元素中的混亂部分,同時模仿使用圖標(biāo)字體的好處!
總結(jié)
到此這篇關(guān)于在 Vue 中編寫 SVG 圖標(biāo)組件的文章就介紹到這了,更多相關(guān)vue SVG 圖標(biāo)組件內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
vue對storejs獲取的數(shù)據(jù)進(jìn)行處理時遇到的幾種問題小結(jié)
這篇文章主要介紹了vue對storejs獲取的數(shù)據(jù)進(jìn)行處理時遇到的幾種問題小結(jié),需要的朋友可以參考下2018-03-03VueCLI通過process.env配置環(huán)境變量的實現(xiàn)
本文主要介紹了VueCLI通過process.env配置環(huán)境變量的實現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2023-07-07