EmojiPicker 表情面板
表情选择面板。六组内置表情,附最近使用。
基础用法
最近选择:(尚未选择)
vue
<script setup>
function onSelect(emoji) {
// emoji.native 是字符本身,emoji.shortcode 是 :smile: 这样的短代码
text.value += emoji.native
}
</script>
<template>
<SrEmojiPicker @select="onSelect" />
</template>数据结构
选中项包含三个字段:
ts
interface SrEmojiItem {
native: string // 字符本身:😀
shortcode: string // 短代码::grinning:
keywords?: string[] // 搜索关键词
}native 与 shortcode 都要留:
- 存进正文用
native——它是用户看到的那个字符,不需要额外渲染逻辑; - 但筛选与搜索要用
shortcode——native是四字节的 emoji, 在部分数据库与旧系统的排序规则下会出现乱码或匹配异常。
搜索与最近使用
面板顶部有搜索框,支持按短代码与关键词匹配。 「最近使用」会在同一浏览器内跨会话保留——数据存在 localStorage。
vue
<SrEmojiPicker :recent-limit="12" @select="onSelect" />「最近使用」是本地存储,不跨设备
不同设备上的使用习惯本就不同(手机与电脑常发的表情差异很大), 而且跨设备同步需要账号体系——组件库不该引入这种依赖。
需要服务端同步时,在 @select 里自行上报即可。
列数与尺寸
vue
<SrEmojiPicker :columns="6" :image-size="26" />
<SrEmojiPicker :columns="10" :image-size="22" />columns 与 imageSize 需要配套调整:列数越多、单个越要小, 否则宽度会撑破容器。
自定义表情包
packages 传入自定义数据后,内置的六组会被完全替换—— 不是追加,是替换。
这一组还没有表情
只保留自定义的一组
vue
<script setup>
const packages = [
{
name: '自定义',
emojis: [
{ native: '🐟', shortcode: ':fish:' },
{ native: '🌊', shortcode: ':wave:' }
]
}
]
</script>
<template>
<SrEmojiPicker :packages="packages" />
</template>传 packages 会替换而非追加
这是有意的——否则「只想用自己那几组」的场景还得先想办法把内置的删掉。
需要在内置基础上追加时,从 DEFAULT_EMOJI_PACKAGES 展开:
ts
import { DEFAULT_EMOJI_PACKAGES } from '@starriver/ui'
const packages = [...DEFAULT_EMOJI_PACKAGES, myPackage]关于渲染 Markdown 里的表情
SrComment 与 SrMarkdown 都能把正文里的 :shortcode: 渲染成表情字符。 它们内部用同一套解析逻辑,因此短代码定义必须一致—— 若给 SrEmojiPicker 传了自定义包,记得也给它们传。
Props
| 名称 | 类型 | 默认值 | 说明 |
|---|---|---|---|
packages | SrEmojiPackage[] | 内置六组 | 表情包数据,会替换内置 |
recentLimit | number | 16 | 「最近使用」最多保留几个 |
columns | number | 8 | 每行几个 |
imageSize | number | 28 | 单个表情尺寸(px) |
事件
| 事件 | 参数 | 说明 |
|---|---|---|
select | SrEmojiItem | 选中某个表情 |
无障碍
- 每个表情是
<button>并带aria-label(短代码形式,如「grinning」)—— emoji 字符本身在部分读屏软件下会被念成无意义的描述 - 分组标签用
role="tab",可用方向键在分组间切换 - 搜索框带
aria-label="搜索表情" - 「最近使用」与「搜索」空结果都有明确文案,不是一片空白