ue3 图标选择器组件:IconSelector基于阿里巴巴矢量图

张开发
2026/4/14 1:22:15 15 分钟阅读

分享文章

ue3 图标选择器组件:IconSelector基于阿里巴巴矢量图
Vue3 图标选择器组件IconSelector一、组件介绍IconSelector是一个基于 Element Plus 的图标选择器弹窗组件用于在表单场景中方便用户选择图标。组件集成阿里 iconfont 图标库支持图标搜索、分类展示、实时预览等功能。二、目录结构src/ ├── assets/ │ └── iconfont/ # iconfont 图标资源目录 │ ├── iconfont.css # 图标字体样式CSS 类名定义 │ ├── iconfont.js # 图标字体脚本 │ ├── iconfont.json # iconfont 导出配置图标元数据 │ ├── iconfont.ttf # 字体文件TTF格式兼容性最好 │ ├── iconfont.woff # 字体文件WOFF格式较好的压缩比 │ └── iconfont.woff2 # 字体文件WOFF2格式压缩率最高 │ ├── components/ │ └── IconSelector/ # 图标选择器组件目录 │ ├── IconSelector.vue # 图标选择器主组件 │ └── index.ts # 组件导出文件 │ ├── config/ │ └── iconfont.ts # iconfont 图标配置读取JSON生成图标列表 │ └── views/ └── menu/ └── index.vue # 使用示例菜单管理页面三、核心文件解析3.1 iconfont.json - 图标元数据iconfont 平台导出的 JSON 配置文件包含所有图标的基础信息{id:5153005,name:新产品,font_family:iconfont,css_prefix_text:icon-,glyphs:[{icon_id:34417664,name:ESC,font_class:ESC,unicode:e74a},{icon_id:6149283,name:回车,font_class:huiche,unicode:e651}// ... 更多图标]}关键字段说明字段说明font_family字体族名称CSS 中使用.iconfont调用css_prefix_textCSS 类名前缀使用时需要拼接icon-glyphs图标字形数组glyphs[].name图标中文名称用于搜索展示glyphs[].font_class图标的 CSS 类名不含前缀glyphs[].unicode图标的 Unicode 码点3.2 iconfont.css - 图标样式通过 CSSfont-face定义字体并设置每个图标的伪类样式font-face{font-family:iconfont;src:url(iconfont.woff2)format(woff2),url(iconfont.woff)format(woff),url(iconfont.ttf)format(truetype);}.iconfont{font-family:iconfont!important;font-size:16px;font-style:normal;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;}.icon-ESC:before{content:\e74a;}.icon-huiche:before{content:\e651;}使用方式给元素添加iconfont icon-xxx类即可显示对应图标。3.3 config/iconfont.ts - 图标配置动态读取 iconfont.json生成统一的图标列表供组件使用/** * file iconfont 图标配置文件 * description 管理阿里矢量图标库的图标列表动态读取 iconfont.json * module config/iconfont */importiconfontDatafrom/assets/iconfont/iconfont.json/** * 图标项接口定义 * interface IconItem * property {string} name - 图标名称中文描述 * property {string} fontClass - 图标类名不含 icon- 前缀 * property {string} fullClass - 完整类名iconfont icon-xxx */exportinterfaceIconItem{name:stringfontClass:stringfullClass:string}/** * iconfont.json 中的字形数据接口 * interface GlyphItem */interfaceGlyphItem{icon_id:stringname:stringfont_class:stringunicode:stringunicode_decimal:number}/** * iconfont.json 数据结构接口 * interface IconfontData */interfaceIconfontData{id:stringname:stringfont_family:stringcss_prefix_text:stringdescription:stringglyphs:GlyphItem[]}/** * 图标列表 * description 从 iconfont.json 动态解析的图标列表 * usage 更新 src/assets/iconfont 目录下的文件后列表会自动更新 */exportconsticonList:IconItem[](iconfontDataasIconfontData).glyphs.map(glyph({name:glyph.name,fontClass:glyph.font_class,fullClass:iconfont icon-${glyph.font_class}}))/** * 获取图标名称列表 * returns 图标类名数组 */exportconstgetIconNames():string[]{returniconList.map(iconicon.fontClass)}/** * 根据类名获取图标信息 * param fontClass - 图标类名不含 icon- 前缀 * returns 图标项或 undefined */exportconstgetIconByClass(fontClass:string):IconItem|undefined{returniconList.find(iconicon.fontClassfontClass)}3.4 components/IconSelector/index.ts - 组件导出/** * file 图标选择器组件导出 * description 导出图标选择器组件及其类型定义 * module components/IconSelector */export{defaultasIconSelector}from./IconSelector.vue3.5 components/IconSelector/IconSelector.vue - 组件完整代码template el-popover refpopoverRef placementbottom-start :width400 triggerclick template #reference div classicon-selector-trigger i v-ifmodelValue :classiconfont icon-${modelValue} classselected-icon /i span v-else classplaceholder请选择图标/span el-icon classarrow-iconArrowDown //el-icon /div /template div classicon-selector-popover el-input v-modelsearchKeyword placeholder搜索图标 clearable classsearch-input template #prefix el-iconSearch //el-icon /template /el-input div classicon-list div v-foricon in filteredIcons :keyicon.fontClass classicon-item :class{ active: modelValue icon.fontClass } clickhandleSelectIcon(icon.fontClass) i :classicon.fullClass classicon-display/i span classicon-name{{ icon.name }}/span span classicon-class{{ icon.fontClass }}/span /div /div div v-iffilteredIcons.length 0 classempty-tip 暂无匹配的图标 /div /div /el-popover /template script setup langts /** * 图标选择器组件 * description 基于 iconfont 的图标选择器使用 Font Class 方式引入 */ import { ref, computed } from vue import { ArrowDown, Search } from element-plus/icons-vue import { iconList, type IconItem } from /config/iconfont interface Props { modelValue?: string } interface Emits { (e: update:modelValue, value: string): void } const props definePropsProps() const emit defineEmitsEmits() const searchKeyword ref() const popoverRef ref() const filteredIcons computedIconItem[](() { if (!searchKeyword.value) return iconList const keyword searchKeyword.value.toLowerCase() return iconList.filter(icon icon.name.toLowerCase().includes(keyword) || icon.fontClass.toLowerCase().includes(keyword) ) }) const handleSelectIcon (fontClass: string) { emit(update:modelValue, fontClass) popoverRef.value?.hide() } /script style scoped langscss .icon-selector-trigger { display: flex; align-items: center; justify-content: space-between; padding: 0 11px; height: 32px; border: 1px solid #dcdfe6; border-radius: 4px; cursor: pointer; background-color: #fff; transition: border-color 0.2s; :hover { border-color: #c0c4cc; } .selected-icon { font-size: 20px; color: #606266; } .placeholder { color: #a8abb2; font-size: 14px; } .arrow-icon { color: #a8abb2; margin-left: 8px; } } .icon-selector-popover { .search-input { margin-bottom: 12px; } .icon-list { display: grid; grid-template-columns: repeat(4, 1fr); gap: 8px; max-height: 300px; overflow-y: auto; .icon-item { display: flex; flex-direction: column; align-items: center; justify-content: center; padding: 8px; border: 1px solid #e4e7ed; border-radius: 4px; cursor: pointer; transition: all 0.2s; :hover { border-color: #409eff; background-color: #ecf5ff; } .active { border-color: #409eff; background-color: #ecf5ff; color: #409eff; .icon-name, .icon-class { color: #409eff; } } .icon-display { font-size: 24px; color: #606266; } .icon-name { font-size: 12px; color: #606266; margin-top: 4px; text-align: center; word-break: break-all; line-height: 1.2; } .icon-class { font-size: 10px; color: #909399; margin-top: 2px; text-align: center; word-break: break-all; line-height: 1.2; } } } .empty-tip { text-align: center; color: #909399; padding: 20px 0; font-size: 14px; } } /style3.6 views/menu/index.vue - 使用示例菜单管理页面3.6.1 表格中展示图标!-- 表格图标列 -- template #default{ row } i v-ifrow.icon :classiconfont icon-${row.icon} classtable-icon/i span v-else classtext-placeholder-/span /template.table-icon { font-size: 18px; color: #606266; }3.6.2 表单中选择图标template el-dialog v-modeldialogVisible title菜单配置 width600px el-form :modelmenuForm label-width100px el-form-item label菜单图标 IconSelector v-modelmenuForm.icon / /el-form-item el-form-item label菜单名称 el-input v-modelmenuForm.name placeholder请输入菜单名称 / /el-form-item el-form-item label菜单编码 el-input v-modelmenuForm.number placeholder请输入菜单编码 / /el-form-item el-form-item label组件路径 el-input v-modelmenuForm.component placeholder如: views/menu/index.vue / /el-form-item /el-form template #footer el-button clickdialogVisible false取消/el-button el-button typeprimary clickhandleSubmit确定/el-button /template /el-dialog /template script setup langts import { reactive, ref } from vue import { IconSelector } from /components/IconSelector const dialogVisible ref(false) const menuForm reactive({ icon: , name: , number: , component: }) const handleSubmit () { console.log(提交的表单数据:, menuForm) // 提交逻辑... } /script四、组件状态说明4.1 未选择状态┌──────────────────────────────────┐ │ 请选择图标 ▼ │ └──────────────────────────────────┘4.2 已选择状态┌──────────────────────────────────┐ │ [图标] ▼ │ └──────────────────────────────────┘4.3 展开面板┌──────────────────────────────────┐ │ 搜索图标 ✕ │ ├──────────────────────────────────┤ │ ┌────┐ ┌────┐ ┌────┐ ┌────┐ │ │ │图标│ │图标│ │图标│ │图标│ │ │ │ESC │ │回车│ │下箭│ │上箭│ │ │ └────┘ └────┘ └────┘ └────┘ │ │ ┌────┐ ┌────┐ ┌────┐ ┌────┐ │ │ │图标│ │图标│ │图标│ │图标│ │ │ │系统│ │系统│ │用户│ │组织│ │ │ └────┘ └────┘ └────┘ └────┘ │ └──────────────────────────────────┘五、如何更新图标步骤 1上传图标到 iconfont登录 iconfont上传新的 SVG 图标到你的项目中。步骤 2生成新的字体文件在 iconfont 项目页面点击「下载到本地」获取最新的字体文件。步骤 3替换文件将src/assets/iconfont/目录下的文件全部替换为新版本src/assets/iconfont/ ├── iconfont.css # 替换 ├── iconfont.js # 替换 ├── iconfont.json # 替换核心 ├── iconfont.ttf # 替换 ├── iconfont.woff # 替换 └── iconfont.woff2 # 替换步骤 4重启项目由于iconfont.json是在构建时读取的替换后需要重启开发服务器使配置生效。六、相关工具函数函数说明用法iconList所有图标的列表import { iconList } from /config/iconfontgetIconNames()获取所有图标的 fontClass 数组getIconNames()→[ESC, huiche, ...]getIconByClass(fontClass)根据 fontClass 获取图标信息getIconByClass(jiaoseguanli)→{name, fontClass, fullClass}七、总结IconSelector组件提供了一套完整的图标选择解决方案数据与视图分离图标配置由独立的 JSON 文件管理组件只负责展示和交互动态更新只需替换 iconfont 目录文件即可更新图标库无需修改代码搜索友好支持按名称和类名双重搜索类型安全完整的 TypeScript 类型定义这套方案特别适合后台管理系统中的菜单图标、按钮图标等场景。相关技术栈Vue 3 TypeScript Element Plus Sass iconfont

更多文章