Vue3引入SVG图标的流程步骤
作者:知否技术
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图标的资料请关注脚本之家其它相关文章!