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图标的资料请关注代码网其它相关文章!
发表评论