vue项目引入icon的问题

element-plus

官网给了两类方案

  1. 使用 @element-plus/icons-vue全局注册或手动 import ,写法是 <el-icon><Plus /></el-icon>(注意:如果想这么用组件,必须安装这个包,以及全局注册或手动引入。自动导入时不用安装这个包)
  2. 自动导入 :用 unplugin-icons + unplugin-auto-import 从 Iconify 自动导入任意图标集,并指向 element-plus-vite-starter 模板(注意,自动导入时是直接去图标大本营iconify找element的图标集去了,使用时写法不是官方<Plus />这种,而是<i-ep-plus />

自动导入注意事项

自动导入时的vite配置(同时组件也是自动引入)

  • 带//***注释的下面是本地svg文件自动引入
  • 具体icon格式:i-图标集名-图标名。图标组名用于vite.config.js里 Components/resolvers/IconsResolver/enabledCollections里配置图集名,以及pnpm add -D @iconify-json/图集名
js 复制代码
import path from 'path'
import { defineConfig } from 'vite'
import Vue from '@vitejs/plugin-vue'
import Icons from 'unplugin-icons/vite'
import IconsResolver from 'unplugin-icons/resolver'
import { FileSystemIconLoader } from 'unplugin-icons/loaders'
import AutoImport from 'unplugin-auto-import/vite'
import Components from 'unplugin-vue-components/vite'
import { ElementPlusResolver } from 'unplugin-vue-components/resolvers'

const pathSrc = path.resolve(import.meta.dirname, 'src')

export default defineConfig({
  resolve: {
    alias: {
      '@': pathSrc,
    },
  },
  plugins: [
    Vue(),
    AutoImport({
      // Auto import functions from Vue, e.g. ref, reactive, toRef...
      // 自动导入 Vue 相关函数,如:ref, reactive, toRef 等
      imports: ['vue'],

      // Auto import functions from Element Plus, e.g. ElMessage, ElMessageBox... (with style)
      // 自动导入 Element Plus 相关函数,如:ElMessage, ElMessageBox... (带样式)
      resolvers: [
        ElementPlusResolver(),

        // Auto import icon components
        // 自动导入图标组件
        IconsResolver({
          prefix: 'Icon',
        }),
      ],

      dts: path.resolve(pathSrc, 'auto-imports.d.ts'),
    }),

    Components({
      resolvers: [
        // Auto register icon components
        // 自动注册图标组件
        IconsResolver({
          // 配置图标集合,需要提前npm安装依赖包后再配置进来
          enabledCollections: ['ep', 'material-symbols'],
          //***** 本地 SVG 图标集合(src/assets/icons)*******
          customCollections: ['local'],
        }),
        // Auto register Element Plus components
        // 自动导入 Element Plus 组件
        ElementPlusResolver(),
      ],

      dts: path.resolve(pathSrc, 'components.d.ts'),
    }),

    Icons({
      // *********** 本地 SVG 图标自动引入配置 **********
      customCollections: {
        // 本地 SVG 图标:src/assets/icons/*.svg,用法 <i-local-文件名 />
        // (如果svg图标本身就干净,这个第二个参数可以省略)
        local: FileSystemIconLoader('src/assets/icons', (svg) =>
          // 让图标颜色跟随 el-icon 的 color / CSS color
          svg.replace(/^<svg /, '<svg fill="currentColor" '),
        ),
      },
      //************************************************
    }),
  ],
})

配置中的prefix说明

这是 AutoImport(unplugin-auto-import)里 IconsResolver 的配置,作用与模板里的 <i-ep-xxx /> 不同------它负责在 script(JS 逻辑)中自动导入图标组件

具体效果

prefix: 'Icon' 规定:当代码中出现以 Icon 开头、后接「图集名 + 图标名」(PascalCase)的标识符时,自动导入对应的图标组件,无需手写 import:

js 复制代码
<script setup>
// 没有手写任何 import,下面这行也能直接用
// 等价于:import IconEpEdit from '~icons/ep/edit'
const editIcon = IconEpEdit
</script>

典型使用场景是图标需要作为 JS 值传递,而不是写在模板标签里:

js 复制代码
<script setup>
// ElMessageBox 的 icon 选项、动态组件 :is 等场景
const handleOpen = () => {
  ElMessageBox.confirm('确认删除?', { icon: IconEpWarning })
}


const dynamicIcon = shallowRef(IconEpEdit)
</script>


<template>
  <!-- el-button 的 icon 属性接收的是组件对象,绑定表达式在 script 作用域解析 -->
  <el-button :icon="IconEpEdit">编辑</el-button>
  <component :is="dynamicIcon" />
</template>
和另一处 IconsResolver 的分工
位置 前缀 管什么 例子
Components() 里(默认 i <i-ep-edit /> 模板标签的自动注册 <i-ep-edit />
AutoImport() 里(Iconvite里配置) IconEpEdit script 中标识符的自动导入 const x = IconEpEdit

两者前缀故意设得不同,避免同一个名字被两个插件重复解析。解析记录会写入 src/auto-imports.d.ts,IDE 也能获得类型提示。

简单说:模板里写标签用 <i-ep-edit />,JS 里当变量用 IconEpEdit,AutoImport/resolvers/ IconsResolver/prefix 是后者的开关。

引入本地svg文件

unplugin-icons提供支持,上面的文件里已有相关配置

关键前提:SVG 要"可染色、可缩放"。el-icon 通过 CSS 的 colorfont-size 控制子元素,所以 SVG 需要满足:

  • 颜色fill="currentColor"(或 stroke),不要用写死的颜色值,否则 color 属性无效
  • 尺寸width="1em" height="1em" 或不写宽高只留 viewBox,这样 :size="20" 才能生效

Iconify + unplugin-icons 是当前 Vue 3 主流方案

目前 Vue 3 社区更推荐的方式是基于 Iconify 生态 + SVG 按需加载,主要有两种用法:

方案 A:@iconify/vue(运行时加载)

html 复制代码
<template>
  <Icon icon="mdi:home" />
</template>
<script setup>
import { Icon } from '@iconify/vue'
</script>
  • 优点:使用简单,10 万+图标随时可用
  • 缺点:运行时通过 API 请求图标数据,有网络依赖

方案 B:unplugin-icons(构建时注入,antfu 出品,⭐4.3k)--- 更推荐

html 复制代码
<template>
  <!-- 直接当组件用,构建时自动按需打包,零运行时开销 -->
  <i-mdi-home />
  <i-carbon-settings />
</template>

配置(Vite):

js 复制代码
// vite.config.ts
import Icons from 'unplugin-icons/vite'
import Components from 'unplugin-vue-components/vite'
import IconsResolver from 'unplugin-icons/resolver'

export default defineConfig({
  plugins: [
    Components({
      resolvers: [
        IconsResolver({ prefix: 'i' })
      ]
    }),
    Icons({ compiler: 'vue3', autoInstall: true })
  ]
})

优势总结:

  • 按需编译时注入,零运行时网络请求
  • SSR/SSG 友好
  • 支持 Vue 3 / React / Svelte 等所有主流框架
  • 底层复用 Iconify 的 100+ 图标集(Material Design、Carbon、Tabler、Phosphor 等)
  • 可配合 UnoCSS 使用 <div class="i-mdi-home" /> 纯 CSS 方案
相关推荐
陈随易8 小时前
在Finch用了62亿词元,我认为这是新一代Agent工具之神
前端·人工智能·后端
水域安全老周8 小时前
水趣钓鱼救生衣专利拆解:两级锁紧如何解决落水人衣分离
java·前端·网络
计算机魔术师9 小时前
Anthropic CEO突然喊踩刹车,OpenAI罕见力挺:AI这辆车不能只踩油门了
前端
wing989 小时前
从codex转战workbuddy使用一周的感受
前端·人工智能·后端
EatFan9 小时前
Java接入支付宝 JSAPI 支付保姆教程(二):流程讲解与前后端代码讲解
前端·spring boot·后端·微信小程序·小程序·uni-app
梦想平凡10 小时前
百游棋牌源代码开发搭建教程(五):房间创建、座位分配与请求幂等实现
前端·javascript·数据库·源代码管理
IT_陈寒10 小时前
Redis的Set操作居然能把我的服务整挂了?
前端·人工智能·后端
计算机魔术师11 小时前
Suno 发布 v6 音乐模型,推出 v6、v6-wild、v6-mini 三个版本
前端
whyweplay11 小时前
elpis : DSL动态组件学习
前端
用户9210802628611 小时前
前端 Vue 专栏 06:异步更新机制、任务队列与 nextTick
前端