当前位置: 代码网 > it编程>前端脚本>Vue.js > Vue3引入SVG图标的流程步骤

Vue3引入SVG图标的流程步骤

2024年10月28日 Vue.js 我要评论
1. 前言我们在开发 vue 项目的时候会使用一些前端组件库,例如 element、ant design 等。这些组件库虽然方便,但是也有一些缺点,比如内置的图标太少。例如我们开发医疗、财务、工程等一

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

(0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2025  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com