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

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

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图标 组件库 技术教程

推荐文章

php常用的正则表达式
2024-11-19 03:48:35 +0800 CST
JavaScript数组 splice
2024-11-18 20:46:19 +0800 CST
如何配置获取微信支付参数
2024-11-19 08:10:41 +0800 CST
2025,重新认识 HTML!
2025-02-07 14:40:00 +0800 CST
使用 sync.Pool 优化 Go 程序性能
2024-11-19 05:56:51 +0800 CST
Vue中如何处理异步更新DOM?
2024-11-18 22:38:53 +0800 CST
Plyr.js 播放器介绍
2024-11-18 12:39:35 +0800 CST
20个超实用的CSS动画库
2024-11-18 07:23:12 +0800 CST
markdown语法
2024-11-18 18:38:43 +0800 CST
Elasticsearch 文档操作
2024-11-18 12:36:01 +0800 CST
在 Vue 3 中如何创建和使用插件?
2024-11-18 13:42:12 +0800 CST
使用Vue 3实现无刷新数据加载
2024-11-18 17:48:20 +0800 CST
go错误处理
2024-11-18 18:17:38 +0800 CST
windows下mysql使用source导入数据
2024-11-17 05:03:50 +0800 CST
Vue3中怎样处理组件引用?
2024-11-18 23:17:15 +0800 CST
联系我们
2024-11-19 02:17:12 +0800 CST
ElasticSearch 结构
2024-11-18 10:05:24 +0800 CST
程序员茄子在线接单