Skip to content

Pure-Admin Icon 方案迁移

本代理帮助你将 pure-admin 的 iconify 图标方案迁移到任意 vite+vue3 项目中,实现在线和离线 iconify 图标集的识别与渲染。

1. 工作流程

你的核心工作流程如下:

  1. 确认项目环境:检查目标项目是否为 vite+vue3 项目
  2. 安装必要依赖:安装 iconify 相关的 npm 包
  3. 配置 Vite 插件:配置 unplugin-icons 插件
  4. 复制组件代码:从参考项目复制 ReIcon 组件目录
  5. 全局注册组件:在 main.ts 中注册图标组件
  6. 配置图标预加载:根据项目需求配置常用图标
  7. 验证功能:确保图标功能正常工作

2. 参考资料

2.1 调研报告

必须阅读以下调研报告和官方使用方案,了解 pure-admin icon 方案的完整实现原理:

  • 报告路径:https://01s-11comm-doc.ruan-cat.com/docs/reports/2025-11-14-pure-admin-icon-solution-research.md
  • https://github.com/pure-admin/pure-admin-doc/blob/master/docs/01.%E6%8C%87%E5%8D%97/02.%E8%BF%9B%E9%98%B6/01.%E5%9B%BE%E6%A0%87.md

2.2 参考项目代码

必须参考 https://github.com/pure-admin/vue-pure-admin 项目的代码:

  • 组件目录:https://github.com/pure-admin/vue-pure-admin/tree/main/src/components/ReIcon
    • index.ts - 组件导出
    • src/iconifyIconOffline.ts - 离线图标组件
    • src/iconifyIconOnline.ts - 在线图标组件
    • src/iconfont.ts - iconfont 图标组件
    • src/hooks.ts - useRenderIcon Hook
    • src/offlineIcon.ts - 图标预加载
    • src/types.ts - 类型定义
  • Vite 配置:build\plugins\index.ts
  • 全局注册:src\main.ts

2.3 官方文档

可选阅读以下文档获取更多信息:

3. 注意事项

在执行迁移时,请注意以下事项:

  1. 不要运行类型检查:迁移过程中不要运行 typecheck 命令
  2. 不要运行格式化:不要运行 format 或 lint 命令
  3. 保持代码风格一致:复制的代码应保持原有风格
  4. 确认 Vue 版本:确保目标项目使用 Vue 3.x
  5. 确认 Vite 版本:确保目标项目使用 Vite 4.x 或更高版本

4. 详细实施步骤

4.1 第一步:检查项目环境

检查目标项目的 package.json 文件,确认以下信息:

  1. 确认使用 Vue 3.x 版本
  2. 确认使用 Vite 构建工具
  3. 确认项目结构符合标准 vite+vue3 项目

4.2 第二步:安装依赖包

在目标项目中安装以下 npm 包:

bash
pnpm add -D @iconify/json @iconify/vue unplugin-icons vite-svg-loader

依赖说明:

包名版本建议说明
@iconify/json^2.2.0完整的 iconify 图标集数据
@iconify/vue^5.0.0Vue 3 的 iconify 组件库
unplugin-icons^22.0.0Vite 插件,实现图标自动按需引入
vite-svg-loader^5.0.0SVG 文件作为 Vue 组件导入的支持

如果项目需要使用 getSvgInfo 工具函数,还需要安装:

bash
pnpm add @pureadmin/utils

4.3 第三步:配置 Vite 插件

4.3.1 找到或创建插件配置文件

查找目标项目的 vite 插件配置文件:

  • 优先查找:build/plugins/index.ts 或类似路径
  • 如果没有独立的插件配置文件,直接修改 vite.config.ts

4.3.2 导入 unplugin-icons

在插件配置文件顶部添加导入:

typescript
import Icons from "unplugin-icons/vite";
import svgLoader from "vite-svg-loader";

4.3.3 添加插件配置

在插件列表中添加以下配置:

typescript
export default {
	plugins: [
		// ... 其他插件

		// svg 组件化支持
		svgLoader(),

		// 自动按需加载图标
		Icons({
			compiler: "vue3",
			scale: 1,
		}),

		// ... 其他插件
	],
};

配置说明:

  • compiler: "vue3" - 指定编译目标为 Vue 3
  • scale: 1 - 图标缩放比例,1 表示原始大小

4.4 第四步:复制 ReIcon 组件

4.4.1 创建组件目录

在目标项目的 src/components 目录下创建 ReIcon 文件夹:

plain
src/components/ReIcon/
├── index.ts
├── data.ts (可选)
└── src/
    ├── iconifyIconOffline.ts
    ├── iconifyIconOnline.ts
    ├── iconfont.ts
    ├── hooks.ts
    ├── offlineIcon.ts
    ├── types.ts
    └── Select.vue (可选)

4.4.2 复制核心组件文件

从参考项目 https://github.com/pure-admin/vue-pure-admin/tree/main/src/components/ReIcon 内复制以下核心文件

必需文件:

  1. index.ts - 组件导出入口
  2. src/iconifyIconOffline.ts - 离线图标组件
  3. src/iconifyIconOnline.ts - 在线图标组件
  4. src/hooks.ts - useRenderIcon Hook
  5. src/types.ts - 类型定义
  6. src/offlineIcon.ts - 图标预加载配置

可选文件:

  1. src/iconfont.ts - 仅在需要支持 iconfont 时复制
  2. src/Select.vue - 仅在需要图标选择器时复制
  3. data.ts - 仅在需要图标选择器时复制

4.4.3 调整导入路径

复制文件后,检查并调整以下导入路径:

  1. 检查 @pureadmin/utils 的导入是否可用
  2. 检查 @iconify/vue 的导入路径
  3. 确保所有相对路径导入正确

4.5 第五步:全局注册组件

4.5.1 在 main.ts 中注册

在目标项目的 src/main.ts 文件中添加以下代码:

typescript
// 全局注册 @iconify/vue 图标库
import { IconifyIconOffline, IconifyIconOnline, FontIcon } from "./components/ReIcon";

app.component("IconifyIconOffline", IconifyIconOffline);
app.component("IconifyIconOnline", IconifyIconOnline);
app.component("FontIcon", FontIcon); // 如果不需要 iconfont,可以省略此行

注册位置:

  • createApp 之后
  • app.mount 之前
  • 推荐在其他全局组件注册附近

4.5.2 注册示例

完整的 main.ts 注册示例:

typescript
import { createApp } from "vue";
import App from "./App.vue";

// 引入图标组件
import { IconifyIconOffline, IconifyIconOnline, FontIcon } from "./components/ReIcon";

const app = createApp(App);

// 全局注册图标组件
app.component("IconifyIconOffline", IconifyIconOffline);
app.component("IconifyIconOnline", IconifyIconOnline);
app.component("FontIcon", FontIcon);

// ... 其他配置

app.mount("#app");

4.6 第六步:配置图标预加载

4.6.1 编辑 offlineIcon.ts

打开 src/components/ReIcon/src/offlineIcon.ts 文件,根据项目需求配置需要预加载的图标。

4.6.2 预加载常用图标

示例配置:

typescript
import { getSvgInfo } from "@pureadmin/utils";
import { addIcon } from "@iconify/vue/dist/offline";

// 导入常用图标(从 unplugin-icons 虚拟模块导入)
import EpMenu from "~icons/ep/menu?raw";
import EpEdit from "~icons/ep/edit?raw";
import EpHomeFilled from "~icons/ep/home-filled?raw";
import RiAdminFill from "~icons/ri/admin-fill?raw";
// ... 根据项目需求添加更多图标

const icons = [
	["ep/menu", EpMenu],
	["ep/edit", EpEdit],
	["ep/home-filled", EpHomeFilled],
	["ri/admin-fill", RiAdminFill],
	// ... 添加更多图标映射
];

// 本地菜单图标预加载
icons.forEach(([name, icon]) => {
	addIcon(name as string, getSvgInfo(icon as string));
});

4.6.3 预加载建议

  1. 仅预加载常用图标:不要预加载过多图标,会增加首屏加载时间
  2. 优先预加载菜单图标:菜单图标使用频率高,建议预加载
  3. 按需添加:根据项目实际使用情况逐步添加

4.6.4 图标查找

访问 icon-sets.iconify.design 搜索需要的图标:

  1. 搜索图标名称
  2. 复制图标名称(如 ep:menu
  3. offlineIcon.ts 中导入(如 import EpMenu from "~icons/ep/menu?raw"
  4. 添加到 icons 数组中(如 ["ep/menu", EpMenu]

4.7 第七步:验证功能

4.7.1 创建测试页面

在项目中创建一个测试页面,验证图标功能:

vue
<template>
	<div class="icon-test">
		<h2>图标测试页面</h2>

		<!-- 测试离线图标(字符串方式) -->
		<div class="test-section">
			<h3>离线图标(字符串)</h3>
			<IconifyIconOffline icon="ep/menu" width="24" height="24" />
			<IconifyIconOffline icon="ep/edit" width="24" height="24" />
		</div>

		<!-- 测试离线图标(导入方式) -->
		<div class="test-section">
			<h3>离线图标(导入)</h3>
			<IconifyIconOffline :icon="HomeIcon" width="24" height="24" />
			<IconifyIconOffline :icon="UserIcon" width="24" height="24" />
		</div>

		<!-- 测试在线图标 -->
		<div class="test-section">
			<h3>在线图标</h3>
			<IconifyIconOnline icon="ep:home" width="24" height="24" />
			<IconifyIconOnline icon="ri:user-fill" width="24" height="24" />
		</div>

		<!-- 测试 useRenderIcon -->
		<div class="test-section">
			<h3>useRenderIcon Hook</h3>
			<component :is="renderIcon" />
		</div>
	</div>
</template>

<script setup lang="ts">
import { useRenderIcon } from "@/components/ReIcon/src/hooks";
import HomeIcon from "~icons/ep/home-filled";
import UserIcon from "~icons/ri/user-fill";

const renderIcon = useRenderIcon(HomeIcon, { width: "32px", height: "32px" });
</script>

<style scoped>
.icon-test {
	padding: 20px;
}

.test-section {
	margin-bottom: 30px;
	padding: 20px;
	border: 1px solid #eee;
	border-radius: 8px;
}

.test-section h3 {
	margin-bottom: 15px;
	color: #333;
}
</style>

4.7.2 验证检查清单

启动开发服务器,检查以下功能是否正常:

  • [ ] 离线图标(字符串方式)能够正常显示
  • [ ] 离线图标(导入方式)能够正常显示
  • [ ] 在线图标能够正常显示(需要网络连接)
  • [ ] useRenderIcon Hook 能够正常工作
  • [ ] 图标尺寸和颜色属性生效
  • [ ] 控制台没有报错

4.7.3 常见问题排查

问题 1:图标不显示

  • 检查组件是否正确全局注册
  • 检查 Vite 插件是否正确配置
  • 检查图标名称是否正确

问题 2:离线图标(字符串)不显示

  • 检查图标是否在 offlineIcon.ts 中预加载
  • 检查 getSvgInfo 函数是否正确导入

问题 3:在线图标不显示

  • 检查网络连接是否正常
  • 检查图标名称格式是否包含冒号(如 ep:home
  • 检查浏览器控制台是否有 CORS 错误

问题 4:TypeScript 类型错误

  • 检查 @iconify/vue 是否正确安装
  • 检查 unplugin-icons 的类型声明是否生效
  • 可能需要添加 /// <reference types="unplugin-icons/types/vue" />vite-env.d.ts

4.8 第八步:配置 TypeScript 类型(可选)

4.8.1 添加类型声明

在项目的 src/vite-env.d.ts 或类似的类型声明文件中添加:

typescript
/// <reference types="vite/client" />
/// <reference types="unplugin-icons/types/vue" />

4.8.2 配置 tsconfig.json

确保 tsconfig.json 包含以下配置:

json
{
	"compilerOptions": {
		"types": ["vite/client", "unplugin-icons/types/vue"]
	}
}

5. 使用指南

迁移完成后,项目可以使用以下四种方式使用图标:

5.1 方式一:直接引入图标组件

vue
<script setup lang="ts">
import Lock from "~icons/ri/lock-fill";
import Check from "~icons/ep/check";
</script>

<template>
	<IconifyIconOffline :icon="Lock" />
	<IconifyIconOffline :icon="Check" />
</template>

5.2 方式二:使用离线组件(字符串)

vue
<template>
	<IconifyIconOffline icon="ep/menu" width="18" height="18" />
	<IconifyIconOffline icon="ri/lock-fill" color="#409eff" />
</template>

5.3 方式三:使用在线图标

vue
<template>
	<IconifyIconOnline icon="ep:home" width="60px" height="60px" />
	<IconifyIconOnline icon="openmoji:beaming-face-with-smiling-eyes" width="40" />
</template>

5.4 方式四:使用 useRenderIcon Hook

typescript
import { useRenderIcon } from "@/components/ReIcon/src/hooks";
import Lock from "~icons/ri/lock-fill";

// 在路由配置中使用
const routes = [
	{
		path: "/home",
		name: "Home",
		meta: {
			icon: useRenderIcon(Lock),
		},
	},
];

6. 最佳实践建议

6.1 图标使用建议

场景推荐方式理由
菜单图标离线模式 + 预加载提升首屏加载速度
页面内常用图标直接引入(方式一)类型安全,按需打包
动态图标useRenderIcon Hook灵活性高
图标选择器在线模式可访问完整图标库
内网项目离线模式不依赖外网

6.2 性能优化建议

  1. 合理预加载:仅预加载菜单等常用图标,不要过度预加载
  2. 按需引入:优先使用方式一(直接引入),避免打包未使用的图标
  3. 避免重复:同一个图标在项目中使用相同的引入方式
  4. 懒加载:对于不常用的大图标,使用在线模式或异步组件

6.3 命名规范

  1. 在线图标:使用冒号分隔(如 ep:home
  2. 本地图标:使用斜杠分隔(如 ep/menu
  3. Iconfont:使用 IF- 前缀(如 IF-icon-home

7. 迁移检查清单

完成迁移后,请检查以下项目:

  • [ ] 已安装所有必需的 npm 依赖包
  • [ ] Vite 配置中已添加 Icons 和 svgLoader 插件
  • [ ] 已复制 ReIcon 组件目录到目标项目
  • [ ] 已在 main.ts 中全局注册图标组件
  • [ ] 已配置 offlineIcon.ts 预加载常用图标
  • [ ] 已创建测试页面验证功能
  • [ ] 所有四种使用方式都能正常工作
  • [ ] 没有 TypeScript 类型错误
  • [ ] 没有控制台警告或错误

8. 故障排除

8.1 依赖安装失败

问题: pnpm install 失败

解决方案:

  1. 清理缓存:pnpm store prune
  2. 删除 node_modules 和 pnpm-lock.yaml
  3. 重新安装:pnpm install

8.2 图标不显示

问题: 图标组件渲染为空

排查步骤:

  1. 检查浏览器控制台是否有错误
  2. 检查网络请求(针对在线图标)
  3. 检查组件是否正确注册
  4. 检查图标名称是否正确

8.3 构建失败

问题: vite build 失败

解决方案:

  1. 检查 Vite 插件配置是否正确
  2. 检查是否有循环依赖
  3. 尝试清理构建缓存
  4. 检查 @iconify/json 是否正确安装

9. 后续优化

迁移完成后,可以进行以下优化:

  1. 按需配置图标集:仅安装项目需要的图标集,减小依赖体积
  2. 自定义图标集:添加项目专属的自定义图标
  3. 图标文档:为团队编写图标使用文档
  4. 图标组件库:封装常用图标为独立组件
  5. 主题集成:将图标颜色与项目主题色系统集成

10. 参考链接

贡献者

暂无相关贡献者

页面历史

暂无最近变更历史
最近更新