1. 前言
我们在开发 vue 项目的时候会使用一些前端组件库,例如 element、ant design 等。
这些组件库虽然方便,但是也有一些缺点,比如内置的图标太少。
例如我们开发医疗、财务、工程等一些前端项目,内置的图标不能满足我们的需求。所以我们需要引入外部的图标。
我们常常在 vue 项目中引入 svg 图标。
2. 效果展示

3. svg 简介
svg 指可伸缩矢量图形 (scalable vector graphics)。
svg 是使用 xml 来描述二维图形和绘图程序的语言。
说白了 svg 就跟 jpg、png 一样,都是图形。只不过这玩意是用 xml 语言设计开发的矢量图。
因为是矢量图,所以不管放大还是缩小,都不会失真。
我们分别看3个相同名称不同尺寸的 svg 图标:

我们用 vscode 打开一个 svg 图标,发现它由很多标签组成:

如果想深入了解 svg ,大家可以去以下网站学习
https://www.runoob.com/svg/svg-tutorial.html https://developer.mozilla.org/zh-cn/docs/web/svg
4. 下载 svg 图标
网上可以下载 svg 图标的网站有很多,这里我强烈推荐阿里巴巴的 iconfont ,因为它有海量免费的图标供大家学习使用。
官网:
https://www.iconfont.cn/

1.选择图标,点击下载按钮

2.选择颜色和尺寸之后,点击下载 svg 格式


3.添加到购物车,批量下载
我们也可以将要下载的图标添加到购物车,然后批量下载


下载之后,接下来我们需要 在 vue 项目中引入这些图标。
5. vue3 引入 svg 图标
前提:使用 vite 脚手架开发 vue3 项目。
在 vite 中使用 vue3 引入 svg 图标,我们需要借助以下插件:
vite-plugin-svg-icons
vite-plugin-svg-icons 是一个 vite 插件,它的主要功能是将 svg 图标转换为 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 用来动态导入所有 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. 开发 svg 搜索组件

这里我们使用 element-plus 作为前端组件库。
我们主要用到 el-input、el-popover、el-scrollbar、el-tooltip 组件。
在 components 文件夹下新建 selecticon 组件

在开发这个组件之前,我们先想一下流程:
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.筛选图标需要根据所有 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 指令的默认事件,用于在组件内部通知父组件更新绑定的值。
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); // 弹窗显示状态
const alliconnames = ref([]); // 所有的图标名称集合
const filtericonnames = ref([]); // 筛选之后名称集合
const filtervalue = ref(""); // 筛选的值
// 修改父组件关联的值
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图标的流程步骤的详细内容,更多关于vue3引入svg图标的资料请关注代码网其它相关文章!
发表评论