优雅的在vue3.0+vite项目中管理自己的Icon

4,869 阅读1分钟

项目中使用icon的方式有很多种,比如阿里巴巴的iconfont就很适合团队开发,那么今天我们来说的是另一种方法iconify

介绍

Iconify 是最通用的图标框架。

  • 可以与任何图标库一起使用的统一图标框架。
  • 开箱即用包括 100 多个图标集,其中包含超过 100,000 个图标。
  • 使用 SVG 框架或前端框架的组件在 HTML 中嵌入图标。
  • 使用 Figma、Sketch 和 Adob​​e XD 插件在设计中嵌入图标。
  • 使用 Iconify Icon Finder 为您的应用程序添加图标搜索。 最后我们附上官网地址,在官网里面可以查看图标库里面的所有Icon

安装

Iconify SVG 框架旨在尽可能易于使用。你可以

<script src="https://code.iconify.design/2/2.1.0/iconify.min.js"></script>
//or
<script src="https://cdn.jsdelivr.net/npm/@iconify/iconify@2.1.0/dist/iconify.min.js"></script>

如果你正在使用webpack、vite、rollup之类的打包工具构建项目,你可以

在vite中使用:

1.安装依赖

yarn add @iconify/iconify --save
yarn add vite-plugin-purge-icons @iconify/json -D

2.配置vite.config.js文件

// vite.config.js
import PurgeIcons from 'vite-plugin-purge-icons'

export default {
  plugins: [
    PurgeIcons({
      /* PurgeIcons Options */
    })
  ]
}

如何使用

在项目中你可以这样使用,其中data-icon来设置icon的名字

<span class="iconify" data-icon="eva:people-outline"> </span>

封装组件

在项目中我们肯定不能拿来直接用,通常是封装成一个通用组件。下面是我项目中封装的一个全局组件,仅供大家参考。

// Icon.vue
<template>
  <div>
    <span ref="elRef" :class="[$attrs.class, 'anticon']" :style="getWrapStyle"></span>
  </div>
</template>
<script lang="ts" setup>
interface Props {
  icon: string; //icon的名字
  size?: number; //字体大小
  color?: string; //字体颜色
}
import { renderSVG } from "@iconify/iconify";
import { onMounted, ref, unref, nextTick, computed, CSSProperties } from "vue";
const props = withDefaults(defineProps<Props>(), {
  size: 16,
  color: "white"
});

const elRef = ref<Element>();
const getWrapStyle = computed((): CSSProperties => {
  return {
    color: props.color,
    fontSize: `${props.size}px`,
    display: "inline-flex"
  };
});

const update = async () => {
  const el = unref(elRef);
  if (!el) return;
  await nextTick();
  const svg = renderSVG(props.icon);
  if (!svg) {
    const span = document.createElement("span");
    span.className = "iconify";
    span.dataset.icon = props.icon;
    el.textContent = "";
    el.appendChild(span);
  } else {
    el.textContent = "";
    el.appendChild(svg);
  }
};

onMounted(() => {
  update();
});
</script>
<style lang="scss" scoped></style>

使用组件

<template>
    <Icon :icon="mdi:content-copy"></Icon>
</template>