编程 Vue3如何引入SVG图标?一篇文章快速学会!

2024-11-18 09:39:49 +0800 CST views 460

Vue3如何引入SVG图标?一篇文章快速学会!

1. 前言

在开发 Vue 项目时,我们常使用前端组件库,如 Element 和 Ant Design,但这些库的内置图标通常较少,无法满足某些特定项目的需求(如医疗、财务等)。因此,很多时候我们需要引入外部 SVG 图标。

2. 效果展示

接下来,我们将学习如何在 Vue3 项目中引入 SVG 图标。

3. SVG 简介

SVG 是可伸缩矢量图形(Scalable Vector Graphics)的简称,使用 XML 来描述二维图形。与 JPG、PNG 一样,SVG 是一种图形格式,但因为它是矢量图,无论放大或缩小都不会失真。

如果想深入了解 SVG,可以参考以下网站:

4. 下载 SVG 图标

推荐使用阿里巴巴的 Iconfont 网站下载 SVG 图标:

  1. 选择图标并点击下载按钮
  2. 设置颜色和尺寸后下载 SVG 格式
  3. 可以将多个图标添加到购物车,批量下载

接下来,我们将在 Vue 项目中引入这些 SVG 图标。

5. Vue3 引入 SVG 图标

5.1 安装插件

我们使用 Vite 脚手架开发 Vue3 项目,并借助 vite-plugin-svg-icons 插件将 SVG 图标转换为 Vue 组件。

首先,安装相关插件:

npm i vite-plugin-svg-icons -D
npm i fast-glob -D  # 如果出现错误,再安装 fast-glob

5.2 在 main.js 中注册插件

main.js 中导入插件:

import 'virtual:svg-icons-register';

5.3 配置 vite.config.js

修改 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, "./src"),
    },
  },
});

5.4 封装展示 SVG 图标的组件

我们封装一个 SvgIcon 组件,用来展示 SVG 图标:

<template>
  <svg aria-hidden="true" :fill="color" :style="'width:' + size + ';height:' + size">
    <use :xlink:href="symbolId" />
  </svg>
</template>

<script setup>
import { computed } from "vue";

const props = defineProps({
  name: {
    type: String,
    default: "",
  },
  color: {
    type: String,
    default: "black",
  },
  size: {
    type: String,
    default: "1em",
  },
});

const symbolId = computed(() => `#icon-${props.name}`);
</script>

5.5 使用组件

使用封装好的 SvgIcon 组件:

<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 图标

我们可以使用 import.meta.glob 来动态导入所有 SVG 图标,并获取图标名称:

<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, ref } from "vue";

const allIconNames = ref([]);  // 存储所有图标名称

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);
  }
};
</script>

<style lang="scss" scoped></style>

7. 开发 SVG 搜索组件

在这个组件中,我们将使用 element-plus 作为前端组件库,开发一个图标选择组件,方便用户搜索和选择 SVG 图标。

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"
    >
      <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-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>
    </el-popover>
  </div>
</template>

<script setup>
import SvgIcon from "@/components/SvgIcon/index.vue";
import { ref, onMounted, toRef } 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,
    default: "",
  },
});

const inputIconValue = toRef(props, "modelValue");

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;
};

const filterIcon = () => {
  if (filterValue.value) {
    filterIconNames.value = allIconNames.value.filter(iconName =>
      iconName.includes(filterValue.value)
    );
  } else {
    filterIconNames.value = allIconNames.value;
  }
};

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>
.icon-list {
  display: flex;
  flex-wrap: wrap;
  .icon-item {
    display: flex;
    justify-content: center;
    padding: 5px;
    margin: 5px;
    width: 10%;
    cursor: pointer;
    border: 1px solid #ccc;
    &:hover {
      border-color: var(--el-color-primary);
      transform: scale(1.1);
      transition: all 0.2s;
    }
  }
}
</style>

images

8. 项目完整代码

可以下载完整项目,记得运行 npm install 来安装相关依赖:

链接: 百度网盘 提取码: 1234

复制全文 生成海报 前端开发 Vue SVG图标 组件库 技术教程

推荐文章

JavaScript 异步编程入门
2024-11-19 07:07:43 +0800 CST
MySQL数据库的36条军规
2024-11-18 16:46:25 +0800 CST
CSS Grid 和 Flexbox 的主要区别
2024-11-18 23:09:50 +0800 CST
php指定版本安装php扩展
2024-11-19 04:10:55 +0800 CST
使用Python提取图片中的GPS信息
2024-11-18 13:46:22 +0800 CST
nginx反向代理
2024-11-18 20:44:14 +0800 CST
Shell 里给变量赋值为多行文本
2024-11-18 20:25:45 +0800 CST
Golang 中你应该知道的 Range 知识
2024-11-19 04:01:21 +0800 CST
38个实用的JavaScript技巧
2024-11-19 07:42:44 +0800 CST
thinkphp swoole websocket 结合的demo
2024-11-18 10:18:17 +0800 CST
使用 node-ssh 实现自动化部署
2024-11-18 20:06:21 +0800 CST
Rust 高性能 XML 读写库
2024-11-19 07:50:32 +0800 CST
Nginx rewrite 的用法
2024-11-18 22:59:02 +0800 CST
PHP如何进行MySQL数据备份?
2024-11-18 20:40:25 +0800 CST
Go 开发中的热加载指南
2024-11-18 23:01:27 +0800 CST
介绍 Vue 3 中的新的 `emits` 选项
2024-11-17 04:45:50 +0800 CST
什么是Vue实例(Vue Instance)?
2024-11-19 06:04:20 +0800 CST
Web 端 Office 文件预览工具库
2024-11-18 22:19:16 +0800 CST
使用Python实现邮件自动化
2024-11-18 20:18:14 +0800 CST
Python Invoke:强大的自动化任务库
2024-11-18 14:05:40 +0800 CST
MySQL 主从同步一致性详解
2024-11-19 02:49:19 +0800 CST
Vue3中如何处理WebSocket通信?
2024-11-19 09:50:58 +0800 CST
Vue3中如何处理异步操作?
2024-11-19 04:06:07 +0800 CST
16.6k+ 开源精准 IP 地址库
2024-11-17 23:14:40 +0800 CST
php内置函数除法取整和取余数
2024-11-19 10:11:51 +0800 CST
总结出30个代码前端代码规范
2024-11-19 07:59:43 +0800 CST
百度开源压测工具 dperf
2024-11-18 16:50:58 +0800 CST
程序员茄子在线接单