- 前端
- UI组件
【免费下载链接】emoji-mart
🏪 One component to pick them all
@emoji-mart/react是 Emoji Mart 官方为 React 生态提供的桥接包装层,它把基于 Preact 编写、可在任意前端框架下运行的 emoji-mart 核心 Picker 以纯 React 组件的形态暴露出来,让 React 开发者只需一行<Picker data={data} onEmojiSelect={...} />即可获得完整的表情选择能力。本指南将围绕该包装器的安装、基本用法、底层运行机制与全部可配置参数展开,读完你不仅能快速接入一个可用的表情选择器,还能理解包装器与核心库之间的数据同步方式,从而针对搜索、皮肤、主题、自定义表情等场景做出精准的定制。
一、包定位:React 生态中的 Emoji Mart 入口
Emoji Mart 采用 monorepo 结构(见根目录 package.json 的workspaces配置),核心代码分为若干相互独立的包。与 React 集成直接相关的是三个:
| 包名 | 版本 | 职责 |
|---|---|---|
emoji-mart | 5.6.0 | 核心表情选择器,基于 Preact 实现,导出Picker、Emoji组件与初始化函数(见 packages/emoji-mart/package.json) |
@emoji-mart/data | 1.2.1 | 表情数据源,按 Emoji 版本(如 15)与图片风格(apple/google/twitter 等)组织 JSON,并附带 22 种语言的 i18n 文件(见 packages/emoji-mart-data/package.json) |
@emoji-mart/react | 1.1.1 | React 包装器,对emoji-mart的Picker做薄封装(见 packages/emoji-mart-react/package.json) |
@emoji-mart/react的定位可以从其 peerDependencies 看出端倪:它声明emoji-mart: ^5.2与react: ^16.8 || ^17 || ^18作为对等依赖,也就是说它自身不携带实现,而是依赖宿主项目中的核心包与 React 运行时。^16.8的下限意味着组件依赖 React Hooks(useRef、useEffect),这决定了其底层包装实现的基本形态。
二、安装
官方 README 给出的安装命令是一条命令同时安装三个包:
npm install --save emoji-mart @emoji-mart/data @emoji-mart/react三个包缺一不可,职责划分明确:
emoji-mart:提供可运行的选择器实现;@emoji-mart/data:提供被渲染的表情数据,是Picker的data参数的标准来源;@emoji-mart/react:提供 React 组件形式的包装入口。
如果使用 Yarn 或 pnpm,等价命令为yarn add/pnpm add后跟同样的包名列表。注意emoji-mart是普通依赖而非可选依赖,因为@emoji-mart/react在运行时需要import { Picker } from 'emoji-mart'(见 packages/emoji-mart-react/react.tsx),缺少它会直接导致模块解析失败。
三、基本用法
官方文档给出的最小可用示例只有几行:
import data from '@emoji-mart/data' import Picker from '@emoji-mart/react' function App() { return ( <Picker data={data} onEmojiSelect={console.log} /> ) }要点拆解:
import data from '@emoji-mart/data':@emoji-mart/data的main字段指向sets/15/native.json(见 packages/emoji-mart-data/package.json),因此直接导入得到的是 Emoji 15 版本、native(系统原生)风格的表情数据集。<Picker data={data} />:data是必传的关键参数,它告诉 Picker 使用哪份数据渲染。onEmojiSelect={console.log}:用户点击任意表情时触发回调,回调签名是(emojiData, event)——第一个参数为解析后的表情数据对象(含id、name、skins、unified等字段),第二个参数为点击事件。这也是把表情写入输入框、聊天区或富文本编辑器的主要出口。
四、包装器内部机制:一次渲染、持续同步
@emoji-mart/react的整个实现只有 22 行(见 packages/emoji-mart-react/react.tsx),却完成了一个关键任务:把 Preact 组件的生命周期翻译成 React 组件的生命周期。
import React, { useEffect, useRef } from 'react' import { Picker } from 'emoji-mart' export default function EmojiPicker(props) { const ref = useRef(null) const instance = useRef(null) if (instance.current) { instance.current.update(props) } useEffect(() => { instance.current = new Picker({ ...props, ref }) return () => { instance.current = null } }, []) return React.createElement('div', { ref }) }其运行逻辑可以拆解为三层:
- 挂载:
useEffect以空依赖数组运行一次,创建一个真正的Picker实例(来自emoji-mart核心包),并把这个实例挂载到div元素上。核心Picker在componentDidMount阶段会执行注册事件监听、建立分类导航等初始化动作(见 packages/emoji-mart/src/components/Picker/Picker.tsx)。 - 更新:每次 React 渲染时,只要
instance.current已存在,就调用instance.current.update(props)把最新的 props 同步给核心实例。核心Picker的componentWillReceiveProps会把这些 props 合并进内部状态,并在custom或categories变化时触发网格重置(见 packages/emoji-mart/src/components/Picker/Picker.tsx)。这一机制保证了 React 状态更新(如切换theme、set、skin)能实时反映到选择器 UI 上。 - 卸载:
useEffect的清理函数将instance.current置空,核心实例随之销毁,事件监听与观察器被回收(对应componentWillUnmount中的unregister,见 packages/emoji-mart/src/components/Picker/Picker.tsx)。
从源码结构可以推断,这种"薄包装 + 实例托管"的设计有两个直接收益:React 侧几乎零开销(不需要维护重复的组件树),且能完整继承核心 Picker 的全部 props 与行为,做到功能零损失。
五、核心 Picker 的完整参数表
@emoji-mart/react直接透传所有 props 给核心Picker,因此核心库的完整配置项即是 React 组件的完整 API。这些参数、默认值与可选值集中定义在 packages/emoji-mart/src/components/Picker/PickerProps.ts 中:
5.1 外观与布局
| 参数 | 默认值 | 可选值 / 说明 |
|---|---|---|
theme | auto | auto/light/dark。auto会通过matchMedia('(prefers-color-scheme: dark)')跟随系统主题并监听变化(见 Picker.tsx) |
set | native | native/apple/facebook/google/twitter,决定表情图片风格 |
skin | 1 | 1~6,默认肤色调 |
emojiSize | 24 | 表情本体尺寸(px) |
emojiButtonSize | 36 | 单个表情按钮尺寸(px),同时参与网格行高与滚动边距计算 |
emojiButtonRadius | 100% | 表情按钮圆角 |
emojiButtonColors | null | 按钮背景色数组,按位置循环取色,可做出多彩棋盘格效果 |
perLine | 9 | 每行表情数量 |
dynamicWidth | false | 开启后依据容器实际宽度动态计算每行数量(依赖ResizeObserver,见 Picker.tsx) |
navPosition | top | 分类导航位置:top/bottom/none |
previewPosition | bottom | 预览区位置:top/bottom/none |
searchPosition | sticky | 搜索框位置:sticky/static/none |
skinTonePosition | preview | 肤色调按钮位置:preview/search/none |
icons | auto | 导航图标风格:auto/outline/solid |
autoFocus | false | 挂载后是否自动聚焦搜索框 |
5.2 数据与内容
| 参数 | 默认值 | 说明 |
|---|---|---|
data | null | 表情数据集,可以是对象或返回 Promise 的函数(延迟加载)。未传入时将从 jsDelivr CDN 按emojiVersion与set拉取(见 config.ts) |
emojiVersion | 15 | 数据版本,可选1/2/3/4/5/11/12/12.1/13/13.1/14/15,对应@emoji-mart/data的sets目录 |
locale | en | 界面语言,支持ar/be/cs/de/es/fa/fi/fr/hi/it/ja/ko/nl/pl/pt/ru/sa/tr/uk/vi/zh共 22 种 |
i18n | null | 自定义文案覆盖,可为对象或函数 |
categories | null | 按分类 id 数组过滤并排序显示的分类 |
custom | null | 自定义表情分类数组,每项含id、name、emojis等字段,会追加进Data.categories(见 config.ts) |
categoryIcons | null | 按分类 id 提供自定义图标 |
exceptEmojis | [] | 要排除的表情 id 数组 |
maxFrequentRows | 4 | “常用”分类最多显示的行数,同时控制本地存储记录的条数 |
noCountryFlags | false | native风格下隐藏国旗表情(依赖SafeFlags白名单过滤,见 config.ts) |
noResultsEmoji | null | 搜索无结果时预览区显示的占位表情 |
previewEmoji | null | 自定义预览区默认表情 |
5.3 回调函数
| 参数 | 说明 |
|---|---|
onEmojiSelect(emojiData, event) | 选择表情时的核心回调 |
onClickOutside(event) | 点击选择器外部时触发 |
onAddCustomEmoji() | 搜索无结果且配置了自定义表情时,显示"添加自定义表情"入口 |
getImageURL(set, unified) | 自定义图片加载 URL 生成器(非 native、非雪碧图模式时使用) |
getSpritesheetURL(set) | 自定义雪碧图 URL 生成器 |
5.4 已废弃参数
stickySearch已被searchPosition取代。若同时传入stickySearch == false与searchPosition == 'sticky',控制台会输出弃用警告,并自动回退为static(见 Picker.tsx)。新代码请直接使用searchPosition。
六、数据加载与初始化原理
data参数看似简单,其背后是一整套初始化管线。核心Picker在渲染前会调用init(props)(见 config.ts),它做了以下几件事:
- 数据获取:
data可以是对象、返回 Promise 的函数,或者省略。省略时按emojiVersion与set拼出 CDN 地址拉取 JSON,例如默认的sets/15/native.json。 - 结构补全:为数据补上
emoticons(颜文字映射)与natives(原生字符映射)索引;将aliases(别名)回填到各表情的aliases数组;在分类列表头部插入frequent(常用)分类。 - i18n 加载:
locale为en时直接使用内置英文文案,其他语言按需从 CDN 拉取对应 JSON。 - 过滤与整理:应用
custom(追加自定义分类)、categories(筛选排序)、exceptEmojis(排除表情)、noCountryFlags(过滤国旗)等规则;为每个表情构建search索引字段(拼接 id、名称分词、关键词、颜文字、原生字符,见 config.ts)。 - 搜索索引重建:若上述步骤导致索引失效,会调用
SearchIndex.reset()重建。
这也是为什么官方示例必须显式传入data——它让打包器把数据作为本地静态资源内联,避免运行时依赖 CDN 网络请求,对离线场景与构建产物可控性都更友好。
七、实战组合:一个定制化的 React 选择器
把上述参数组合起来,可以得到一个覆盖典型业务需求的完整示例:
import data from '@emoji-mart/data' import Picker from '@emoji-mart/react' import zh from '@emoji-mart/data/i18n/zh.json' function ChatEmojiPicker({ onPick, onClose }) { return ( <Picker data={data} // 本地内联数据,避免运行时拉 CDN locale="zh" // 中文界面 i18n={zh} // 显式传入中文文案,保证离线可用 theme="auto" // 跟随系统深浅色 set="apple" // 使用 Apple 风格表情图片 perLine={10} // 每行 10 个 emojiButtonSize={40} // 更大触控区域 previewPosition="top" // 预览区置顶 navPosition="bottom" // 分类导航置底 maxFrequentRows={2} // 常用分类只留两行 onEmojiSelect={onPick} // 表情选中回调 onClickOutside={onClose} // 点击外部关闭 /> ) }使用时的注意事项:
set与data的匹配:set决定表情图片风格与数据包的sets子目录。若使用apple等非 native 风格,默认会从 emoji-datasource CDN 加载图片;如需完全离线,可通过getImageURL/getSpritesheetURL提供自托管资源地址(对应核心实现见 Emoji.tsx)。- 动态布局:在窄容器(如输入框弹层)中使用时建议开启
dynamicWidth,Picker会借助ResizeObserver按容器实际宽度重算每行数量,避免表情按钮溢出。 - 数据版本:默认数据为 Emoji 15 版本,可通过
emojiVersion配合对应版本的@emoji-mart/data包灵活切换(数据包sets目录下提供 1~15 各版本,见 packages/emoji-mart-data/sets)。
八、性能设计:为什么千级表情也能流畅渲染
从核心源码可以观察到,Picker为渲染大量表情做了针对性优化,理解这些机制有助于在 React 项目中合理使用:
- 按行懒渲染:
Performance.rowsPerRender = 10,每 10 行为一组;只有进入视口的行才真正渲染(见 Picker.tsx 与renderCategories中的visibleRows判断)。 - IntersectionObserver 双观察:一个观察分类区块以联动顶部导航高亮,另一个观察行可见性以驱动懒渲染(见 Picker.tsx)。
- PureInlineComponent 隔离重绘:每个表情按钮被 HOC 包裹,只有
selected、skin、size变化时才重渲染自身,避免整个网格随悬停状态抖动(见 packages/emoji-mart/src/components/HOCs/PureInlineComponent.ts)。 - 键盘导航闭环:搜索框支持方向键移动高亮、Enter 选择、Escape 清空/失焦,并有
mouseIsIgnored机制防止键盘操作后鼠标误触发(见 Picker.tsx)。
九、延伸阅读
- 核心选择器实现:packages/emoji-mart/src/components/Picker/Picker.tsx
- 全部 props 定义与默认值:packages/emoji-mart/src/components/Picker/PickerProps.ts
- 数据初始化与 i18n 管线:packages/emoji-mart/src/config.ts
- 表情渲染(图片/native/雪碧图三种模式):packages/emoji-mart/src/components/Emoji/Emoji.tsx
- React 包装器实现:packages/emoji-mart-react/react.tsx
- 数据包结构(sets 与 i18n):packages/emoji-mart-data
- 主项目文档:README.md
综上,@emoji-mart/react是一个"薄到极致"的官方 React 适配层,真正的能力全部沉淀在emoji-mart核心库中。掌握安装命令、包装器的实例托管机制,以及透传 props 的完整参数表,即可在 React 16.8+ / 17 / 18 项目中快速落地一个支持搜索、分类导航、肤色调、深浅主题与自定义表情的完整表情选择器。
- 前端
- UI组件
【免费下载链接】emoji-mart
🏪 One component to pick them all
相关推荐
终极表情选择器:Emoji Mart完全指南
终极表情选择器:Emoji Mart完全指南 想要在网页应用中快速集成强大的表情选择功能吗?Emoji Mart正是你需要的终极解决方案!作为一款高度可定制的表
前端UI组件终极表情选择器指南:Emoji Mart完全解析
终极表情选择器指南:Emoji Mart完全解析 在现代Web开发中,表情选择器已经成为提升用户体验的重要组件。Emoji Mart作为一款高度可定制的表情选择
前端UI组件Emoji Mart与PWA集成:打造离线可用的表情选择器终极指南
Emoji Mart与PWA集成:打造离线可用的表情选择器终极指南 Emoji Mart 是一个功能强大的网页表情选择器组件,通过将其与 PWA(渐进式Web应
前端UI组件
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考