news 2026/9/21 3:29:01

在 React Native 中使用 Evil Icons:@react-native-vector-icons/evil-icons 字体包完整指南

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
在 React Native 中使用 Evil Icons:@react-native-vector-icons/evil-icons 字体包完整指南

在 React Native 中使用 Evil Icons:@react-native-vector-icons/evil-icons 字体包完整指南

【免费下载链接】react-native-vector-iconsCustomizable Icons for React Native with support for image source and full styling.项目地址: https://gitcode.com/gh_mirrors/re/react-native-vector-icons

Evil Icons 是一套线条风格(stroke-based)的图标字体,本文以仓库中的 packages/evil-icons/README.md 为主线,系统讲解@react-native-vector-icons/evil-icons的安装、动态/静态两种导入方式、Expo 配置插件接入,并结合仓库源码(createIconSet实现、glyphmap、Android 原生包)深入说明其底层工作原理。读完本文,你将能够在 React Native 与 Expo 项目中正确、高效地集成 Evil Icons,并理解两种字体加载策略的取舍。

一、Evil Icons 字体包是什么

Evil Icons 是 react-native-vector-icons 生态中面向 Evil Icons 字体(上游版本 1.10.1)的独立包。与直接依赖整个 react-native-vector-icons 不同,当前仓库采用"每个图标集一个独立 npm 包"的 monorepo 结构,@react-native-vector-icons/evil-icons即对应 packages/evil-icons 目录,包内包含:

  • fonts/EvilIcons.ttf:字体文件本体;
  • glyphmaps/EvilIcons.json:图标名到 Unicode 码点的映射表(共 72 个图标);
  • src/index.ts/src/static.ts:动态加载与静态加载两种入口;
  • app.plugin.js:Expo 配置插件;
  • android/:用于 autolinking 注册的原生包。

从 package.json 可以看到,该包要求node >= 18.0.0,peerDependencies 为reactreact-native,以及可选的@expo/config-plugins(>= 10.0.0,仅在使用 Expo 配置插件时需要)。当前仓库中该包版本为 13.1.2。

二、安装

在 React Native 或 Expo 项目中执行:

npm install @react-native-vector-icons/evil-icons

包内exports字段(见 package.json)暴露了以下子路径,均可直接引用:

子路径用途
@react-native-vector-icons/evil-icons默认入口(动态加载字体)
@react-native-vector-icons/evil-icons/static静态入口(配合原生构建)
@react-native-vector-icons/evil-icons/glyphmaps/*.json图标映射表 JSON
@react-native-vector-icons/evil-icons/fonts/*.ttf字体文件
@react-native-vector-icons/evil-icons/app.plugin.jsExpo 配置插件

三、基础用法

最简单的用法是从默认入口导入组件并渲染:

import { EvilIcons } from '@react-native-vector-icons/evil-icons'; // ... <EvilIcons name="house" color="#ff0000" size={20} />

该 README 还给出了两种入口的取舍建议:

// 静态导入(推荐用于开发构建,避免字体被打包两次) import { EvilIcons } from '@react-native-vector-icons/evil-icons/static'; // 或使用动态字体加载(默认入口,参见 Expo 配置指南) import { EvilIcons } from '@react-native-vector-icons/evil-icons';

组件的核心 props 与 react-native-vector-icons 保持一致:name(图标名)、color(颜色,可传任何TextStyle['color'])、size(字号)。此外还支持stylechildrenallowFontScaling(默认false)与innerRef等属性,完整定义见 packages/common/src/create-icon-set.tsx 中的IconProps

3.1 图标命名与 glyphmap

name的可选值来自 glyphmaps/EvilIcons.json,共 72 个图标,例如:archivearrow-downarrow-leftarrow-rightarrow-upbellcalendarcameracartchartcheckchevron-downchevron-leftchevron-rightchevron-upclockcloseclose-ocommentcredit-cardenvelopeexclamationexternal-linkeyegearheartimagelikelinklocationlockminusnaviconpaperclippencilplaypluspointerquestionredorefreshretweetsc-facebooksc-githubsc-google-plussc-instagramsc-linkedinsc-odnoklassnikisc-pinterestsc-skypesc-soundcloudsc-telegramsc-tumblrsc-twittersc-vimeosc-vksc-youtubesearchshare-appleshare-googlespinnerspinner-2spinner-3startagtrashtrophyundounlockuserhouse

映射表中每个图标名对应一个十进制的 Unicode 码点(如"house": 61696,即 U+F100)。在渲染时,createIconSet内部通过resolveGlyph将码点转换为字符(String.fromCodePoint(glyph)),未知名称则回退为'?',实现见 packages/common/src/create-icon-set.tsx。

3.2 TypeScript 类型支持

两个入口文件都会导出图标名联合类型:

export type EvilIconsIconName = keyof typeof glyphMap;

见 src/index.ts 与 src/static.ts。这意味着nameprop 会获得完整的类型提示与编译期校验,拼写错误的图标名会在编译阶段被拦截。

四、默认入口(动态加载)与静态入口(/static)如何选择

这是本 README 引出的核心话题,完整决策背景见 docs/SETUP-EXPO.md:

  • 默认入口(动态加载)src/index.tscreateIconSet的配置带有fontSource: require('../fonts/EvilIcons.ttf')(见 src/index.ts),Metro 会把.ttf作为 JS 资源打进 bundle。图标首次渲染时,运行时通过expo-font(底层是@react-native-vector-icons/commondynamicLoader)将字体注册到原生文本系统,无需任何原生配置。这是唯一能在 Expo Go 中工作的方式,且字体可以随 OTA 更新。前提是 Expo SDK >= 52。
  • 静态入口(/static)src/static.ts不携带fontSource(见 src/static.ts),Metro 不会打包.ttf。字体由 autolinking 在构建期通过每个包的build.gradle/.podspec拷贝进原生二进制,再由 Expo 配置插件把它注册进 iOS 的Info.plistUIAppFonts)。该方式只适用于 Development Build,不适用于 Expo Go,且内嵌字体无法通过 OTA 更换。

[!NOTE] 如果只使用默认入口、但又在开发构建中启用了 autolinking,同一个.ttf会同时以 JS 资源与原生资源两种方式进入包体,造成体积翻倍;此时要么改用/static,要么在 autolinking 中排除该包,只保留 JS 侧副本。

关于动态加载,@react-native-vector-icons/common还导出了控制函数:isDynamicLoadingEnabled()isDynamicLoadingSupported()setDynamicLoadingEnabled()setDynamicLoadingErrorCallback(),可用于检测/开关动态加载能力或在 OTA 更新缺失字体时捕获错误。

五、Expo Config Plugin 配置

如果你使用静态导入(/static)并在 Expo 开发构建中运行,需要在app.jsonapp.config.jsplugins数组中注册本包的配置插件:

{ "expo": { "plugins": ["@react-native-vector-icons/evil-icons"] } }

配置完成后执行npx expo prebuild重新生成原生工程。

插件实现见 app.plugin.js:它基于@expo/config-pluginswithInfoPlist,把EvilIcons.ttf追加到UIAppFonts数组(c.modResults.UIAppFonts),从而让 iOS 在应用启动时加载该字体。注意本插件只负责 iOS 侧注册,Android 侧由 autolinking 直接处理字体拷贝。

[!WARNING] 不要重复配置:不要再把node_modules/@react-native-vector-icons/evil-icons/fonts/EvilIcons.ttf手动加入expo-font的 config plugin 配置,否则会造成字体配置重复。

六、底层实现:createIconSet 如何工作

两个入口都基于@react-native-vector-icons/commoncreateIconSet工厂函数构建(packages/common/src/create-icon-set.tsx)。其核心逻辑包括:

  1. 字体引用解析:根据平台生成fontFamily引用——Windows 为/Assets/{fontFileName}#{postScriptName},Android 为字体文件名去扩展名,其余平台使用postScriptName(见fontReferencePlatform.select,create-icon-set.tsx)。
  2. 样式覆盖:强制fontFamily: fontReferencefontWeight: 'normal'fontStyle: 'normal',防止父级文本样式破坏图标字形。
  3. 动态字体加载:当存在fontSource且动态加载开启时,首次渲染通过dynamicLoader.loadFontAsync异步加载字体,加载完成前渲染空字符以避免"豆腐块"(create-icon-set.tsx)。
  4. 图像源 API:组件命名空间上还挂载了getImageSource(异步)与getImageSourceSync(同步)两个静态方法,可把图标转为图片源对象,用于Image组件、TabBarIcon等场景,内部走create-icon-source-cache缓存。

也就是说,<EvilIcons name="house" size={20} color="#ff0000" />最终渲染为一个设置了对应fontFamily与字形字符的<Text>节点。

七、Android 侧原生注册

android/目录下提供了用于 autolinking 的原生包:VectorIconsEvilIconsPackage.kt。它继承BaseReactPackage,但getModule返回nullgetReactModuleInfoProvider返回空映射——从源码结构看,这是一个"占位"包,主要作用是让 autolinking 发现并保留该包的原生构建产物(字体拷贝配置),本身不注册任何原生模块。因此,在纯 JS 渲染场景(如默认动态加载)下,即使不依赖该原生包也能正常工作;静态加载场景则依赖 autolinking 在构建期完成字体拷贝。

八、版本对应关系

README 明确说明:在 12.0.0 版本之前,字体包的版本号直接跟随上游 Evil Icons 版本;12.0.0 之后改为跟随 react-native-vector-icons(RNVI)版本体系。当前对应关系如下:

RNVI 版本上游 Evil Icons 版本
> 12.0.01.10.1

仓库中 package.json 的 devDependencies 锁定evil-icons: 1.10.1,与表格一致;字体生成流程由根目录 scripts/generate-fonts.sh 与字体包生成器(packages/generator-react-native-vector-icons)协作完成,相关演进记录可查看 packages/evil-icons/CHANGELOG.md(如 12.0.0 起"字体包负责字体拷贝"、12.3.0 起导出字体文件与 glyphmaps、13.1.0 起加入 Expo 配置插件)。

九、更多平台与后续参考

  • 不使用 Expo 的纯 React Native 工程,请参考 docs/SETUP-REACT-NATIVE.md;
  • Web 端集成方式见 docs/SETUP-WEB.md;
  • 自定义字体(含 FontAwesome Pro 等 Pro 字体)需通过createIconSet配合fontSource实现,详见 README.md;
  • 仓库的整体架构与全部字体包列表见根目录 README.md;
  • 参与开发请遵循 CONTRIBUTING.md 中的工作流。

十、总结

@react-native-vector-icons/evil-icons是一个高度工程化的字体包:默认入口借助动态字体加载做到"开箱即用、Expo Go 可用、支持 OTA";静态入口配合 Expo 配置插件与 autolinking 做到"原生打包、无 JS 资源冗余"。理解createIconSet的字体引用解析与resolveGlyph字形映射机制,能帮助你在渲染异常、字体重复打包等场景下快速定位根因,并根据 Expo/纯 RN、Expo Go/Development Build 的不同组合选择正确的导入方式。

【免费下载链接】react-native-vector-iconsCustomizable Icons for React Native with support for image source and full styling.项目地址: https://gitcode.com/gh_mirrors/re/react-native-vector-icons

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/21 3:22:23

低功耗Bandgap设计实战:结构、启动电路与验证方法

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/21 3:19:20

SAP MM工厂间调拨:301与303移动类型选型指南与实战避坑

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/21 3:14:35

Modbus RTU现场通信故障排查:地电位、终端电阻与字节序的坑

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/21 3:13:23

public-apis实战指南:从API选型到生产级治理

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华