Vue3引入SVG圖標的流程步驟
1. 前言
我們在開發(fā) Vue 項目的時候會使用一些前端組件庫,例如 Element、Ant Design 等。
這些組件庫雖然方便,但是也有一些缺點,比如內(nèi)置的圖標太少。
例如我們開發(fā)醫(yī)療、財務、工程等一些前端項目,內(nèi)置的圖標不能滿足我們的需求。所以我們需要引入外部的圖標。
我們常常在 Vue 項目中引入 SVG 圖標。
2. 效果展示

3. SVG 簡介
SVG 指可伸縮矢量圖形 (Scalable Vector Graphics)。
SVG 是使用 XML 來描述二維圖形和繪圖程序的語言。
說白了 SVG 就跟 jpg、png 一樣,都是圖形。只不過這玩意是用 xml 語言設計開發(fā)的矢量圖。
因為是矢量圖,所以不管放大還是縮小,都不會失真。
我們分別看3個相同名稱不同尺寸的 SVG 圖標:

我們用 vscode 打開一個 SVG 圖標,發(fā)現(xiàn)它由很多標簽組成:

如果想深入了解 SVG ,大家可以去以下網(wǎng)站學習
https://www.runoob.com/svg/svg-tutorial.html https://developer.mozilla.org/zh-CN/docs/Web/SVG
4. 下載 SVG 圖標
網(wǎng)上可以下載 SVG 圖標的網(wǎng)站有很多,這里我強烈推薦阿里巴巴的 iconfont ,因為它有海量免費的圖標供大家學習使用。
官網(wǎng):
https://www.iconfont.cn/

1.選擇圖標,點擊下載按鈕

2.選擇顏色和尺寸之后,點擊下載 SVG 格式


3.添加到購物車,批量下載
我們也可以將要下載的圖標添加到購物車,然后批量下載


下載之后,接下來我們需要 在 vue 項目中引入這些圖標。
5. Vue3 引入 SVG 圖標
前提:使用 Vite 腳手架開發(fā) Vue3 項目。
在 Vite 中使用 Vue3 引入 SVG 圖標,我們需要借助以下插件:
vite-plugin-svg-icons
vite-plugin-svg-icons 是一個 Vite 插件,它的主要功能是將 SVG 圖標轉(zhuǎn)換為 Vue 組件,并自動導入到項目中。
5.1 安裝插件
npm i vite-plugin-svg-icons -D
安裝之后運行程序如果報這個錯誤,需要再安裝 fast-glob 插件

npm i fast-glob -D
5.2 main.js 中注冊插件
import 'virtual:svg-icons-register'

5.3 配置 vite.config.js
import { defineConfig } from "vite";
import vue from "@vitejs/plugin-vue";
import { createSvgIconsPlugin } from "vite-plugin-svg-icons";
import { resolve } from "path";
const pathSrc = resolve(__dirname, "src");
export default defineConfig({
plugins: [
vue(),
createSvgIconsPlugin({
// 指定需要緩存的圖標文件夾
iconDirs: [resolve(pathSrc, "assets/icons")],
// 指定symbolId格式
symbolId: "icon-[dir]-[name]",
}),],
resolve: {
// 設置別名
alias: {
'@': resolve(__dirname, resolve(__dirname, "./src"))
}
},
});
其中最關鍵的是指定 svg 圖標的存放位置:

5.4 封裝展示 SVG 圖標的 icon 組件
1.:xlink:href 用來綁定圖標的名稱,名稱前要加前綴 icon
2.fill 屬性用來設置圖標的顏色
<template>
<svg aria-hidden="true" :fill="color" :style="'width:' + size + ';height:' + size">
<use :xlink:href="symbolId" rel="external nofollow" />
</svg>
</template>
<script setup>
import { computed } from "vue";
const props = defineProps({
// icon 名字
name: {
type: String,
default: "",
},
// 填充顏色
color: {
type: String,
default: "black",
},
// 大小
size: {
type: String,
default: "1em",
},
});
const symbolId = computed(() => `#icon-${props.name}`);
</script>

5.5 使用組件
<template>
<div class="content">
<SvgIcon name="client" size="10rem" />
<SvgIcon name="client" size="10rem" color="red" />
<SvgIcon name="client" size="10rem" color="green" />
</div>
</template>
<script setup>
import SvgIcon from "@/components/SvgIcon/index.vue";
</script>
<style lang="scss" scoped></style>


6. 批量導入 SVG 圖標
1.import.meta.glob 用來動態(tài)導入所有 svg 圖標
2.獲取所有圖標的名稱
<template>
<div class="content">
<SvgIcon
v-for="(iconName, index) in allIconNames"
:key="index"
:name="iconName"
size="5rem"
/>
</div>
</template>
<script setup>
import SvgIcon from "@/components/SvgIcon/index.vue";
import { onMounted, toRef, ref } from "vue";
const allIconNames = ref([]); // 所有的圖標名稱集合
onMounted(() => {
loadAllIcons();
});
// 獲取所有 icon
const loadAllIcons = () => {
const icons = import.meta.glob("@/assets/icons/*.svg");
for (const icon in icons) {
// 獲取 icon 名稱
const iconName = icon.split("/src/assets/icons/")[1].split(".")[0];
allIconNames.value.push(iconName);
}
};
</script>
<style lang="scss" scoped></style>

7. 開發(fā) SVG 搜索組件

這里我們使用 element-plus 作為前端組件庫。
我們主要用到 el-input、el-popover、el-scrollbar、el-tooltip 組件。
在 components 文件夾下新建 SelectIcon 組件

在開發(fā)這個組件之前,我們先想一下流程:
1.首先封裝 el-input,prepend 需要用 SvgIcon 展示選中圖標,v-model 需要綁定該圖標的名稱。

2.點擊 el-input, 彈出 el-popover,也就是需要給 el-popover 綁定 visible。
3.el-popover上面需要展示搜索框,下面需要展示所有的圖標。
// 加載 icon
onMounted(() => {
loadAllIcons();
});
// 獲取所有圖標
const loadAllIcons = () => {
const icons = import.meta.glob("@/assets/icons/*.svg");
for (const icon in icons) {
const iconName = icon.split("/src/assets/icons/")[1].split(".")[0];
allIconNames.value.push(iconName);
}
filterIconNames.value = allIconNames.value;
};
4.圖標太多需要滾動,所以需要 el-scrollbar 組件進行包裹。

5.篩選圖標需要根據(jù)所有 SVG 的名稱是否包含 filterName
// 篩選 icon
const filterIcon = () => {
if (filterValue.value) {
filterIconNames.value = allIconNames.value.filter((iconName) =>
iconName.includes(filterValue.value)
);
} else {
filterIconNames.value = allIconNames.value;
}
};
6.點擊圖標需要更新父組件綁定的值
update:modelValue 是 v-model 指令的默認事件,用于在組件內(nèi)部通知父組件更新綁定的值。
const handleSelect = (iconName) => {
emit("update:modelValue", iconName);
visible.value = false;
};
<el-form-item label="圖標:" prop="icon" > <icon-select ref="IconSelectRef" v-model="sysMenu.icon" /> </el-form-item>
7.1 SelectIcon 組件完整代碼
<template>
<div class="content">
<el-input
style="width: 100%"
v-model="inputIconValue"
readonly
placeholder="點擊選擇圖標"
@click="visible = !visible"
>
<template #prepend>
<SvgIcon :size="20" :name="inputIconValue" />
</template>
</el-input>
<el-popover
shadow="none"
:visible="visible"
placement="bottom-end"
trigger="click"
width="400"
>
<template #reference>
<div @click="visible = !visible">
<i-ep-caret-top v-show="visible" />
<i-ep-caret-bottom v-show="!visible" />
</div>
</template>
<!-- 下拉選擇彈窗 -->
<div>
<el-row :gutter="10">
<el-col :span="18">
<el-input
v-model="filterValue"
placeholder="輸入圖標名稱"
clearable
@input="filterIcon"
/>
</el-col>
<el-col :span="6">
<el-button @click="closeIcon()">關閉</el-button>
</el-col>
</el-row>
<el-divider border-style="dashed" />
<el-scrollbar height="300px">
<div class="icon-list">
<el-tooltip
v-for="(iconName, index) in filterIconNames"
:key="index"
:content="iconName"
placement="bottom"
effect="light"
>
<div class="icon-item" @click="handleSelect(iconName)">
<SvgIcon :name="iconName" />
</div>
</el-tooltip>
</div>
</el-scrollbar>
</div>
</el-popover>
</div>
</template>
<script setup>
import SvgIcon from "@/components/SvgIcon/index.vue";
import { onMounted, toRef, ref } from "vue";
const visible = ref(false); // 彈窗顯示狀態(tài)
const allIconNames = ref([]); // 所有的圖標名稱集合
const filterIconNames = ref([]); // 篩選之后名稱集合
const filterValue = ref(""); // 篩選的值
// 修改父組件關聯(lián)的值
const emit = defineEmits(["update:modelValue"]);
const props = defineProps({
modelValue: {
type: String,
require: false,
default: "",
},
});
const inputIconValue = toRef(props, "modelValue");
// 加載 icon
onMounted(() => {
loadAllIcons();
});
// 獲取所有圖標
const loadAllIcons = () => {
const icons = import.meta.glob("@/assets/icons/*.svg");
for (const icon in icons) {
const iconName = icon.split("/src/assets/icons/")[1].split(".")[0];
allIconNames.value.push(iconName);
}
filterIconNames.value = allIconNames.value;
};
// 篩選 icon
const filterIcon = () => {
if (filterValue.value) {
filterIconNames.value = allIconNames.value.filter((iconName) =>
iconName.includes(filterValue.value)
);
} else {
filterIconNames.value = allIconNames.value;
}
};
// 選擇 icon
const handleSelect = (iconName) => {
emit("update:modelValue", iconName);
visible.value = false;
};
// 關閉組件
const closeIcon = () => {
visible.value = false;
filterValue.value = "";
filterIconNames.value = allIconNames.value;
};
</script>
<style lang="scss" scoped>
.el-divider--horizontal {
margin: 10px auto !important;
}
.icon-list {
display: flex;
flex-wrap: wrap;
.icon-item {
display: flex;
justify-content: center;
padding: 5px 0px;
margin: 5px;
width: 10%;
cursor: pointer;
border: 1px solid #ccc;
&:hover {
color: var(--el-color-primary);
border-color: var(--el-color-primary);
transition: all 0.2s;
transform: scaleX(1.1);
}
}
}
</style>
以上就是Vue3引入SVG圖標的流程步驟的詳細內(nèi)容,更多關于Vue3引入SVG圖標的資料請關注腳本之家其它相關文章!
相關文章
vue內(nèi)置組件keep-alive事件動態(tài)緩存實例
這篇文章主要介紹了vue內(nèi)置組件keep-alive事件動態(tài)緩存實例,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-10-10
Vue項目中input框focus時不調(diào)出鍵盤問題的解決
這篇文章主要介紹了Vue項目中input框focus時不調(diào)出鍵盤問題的解決,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-04-04

