【前端】Twemoji(Twitter Emoji)
目录
- 注意
- 使用
- Vue / React 项目
- 验证
- Twemoji 的作用:
Twemoji 会把你网页/应用中的 Emoji 字符(如 😄)自动替换为 Twitter 风格的图片(SVG/PNG);
它不依赖系统字体,因此在 Android、Windows、macOS、iOS 等系统上都能显示统一的视觉效果;但显示出来的 不是 Apple emoji的风格,而是 Twitter 的风格。
场景 | 是否能解决 |
---|---|
安卓显示苹果风格 Emoji | 无法使用 Apple 的图形❌ |
安卓系统不支持新 Emoji,无法显示 | 用图像替代,兼容所有新旧设备 |
各系统 Emoji 风格不统一 | Twemoji 保证所有平台一致 |
不依赖用户系统字体 | ✅ |
可自定义大小、样式、加载策略 | ✅ |
注意
npm 包用的也是maxcdn的地址,但是maxcdn已经崩溃了。
之后所有的twemoji.parse都应该修改base
import twemoji from 'twemoji';export default {install(app: any) {app.directive('twemoji', {mounted(el: HTMLElement) {twemoji.parse(el, {base: 'https://cdn.jsdelivr.net/gh/twitter/twemoji@14.0.2/assets/'});},updated(el: HTMLElement) {twemoji.parse(el,{base: 'https://cdn.jsdelivr.net/gh/twitter/twemoji@14.0.2/assets/'});}});}
};
//这样就可以正常加载了
国内源https://cdn.jsdmirror.com/gh/twitter/twemoji@14.0.2/assets/
cdn.jsdmirror.com
- emoji显示大小调整
Twemoji 默认插入的<img>
标签没有限制尺寸,导致显示时占用过多空间。
/* 全局限制 twemoji img 大小 */
img.emoji, img.emoji-svg {display:inline-block;width: 1em;height: 1em;vertical-align: -0.1em; /* 调整与文字基线对齐 */
}
使用
- CDN引入
<script src="https://twemoji.maxcdn.com/v/latest/twemoji.min.js"></script>
- 在页面加载后执行解析
<script>document.addEventListener('DOMContentLoaded', function () {twemoji.parse(document.body, {folder: 'svg', // svg 或 72x72(PNG 图片)ext: '.svg' // 或 '.png'});});
</script>
Vue / React 项目
- 安装
npm install twemoji
- 全局应用 Twemoji(也就是全站的 Emoji 都自动替换为 Twemoji 风格)方案:
框架 | 推荐方式 | 说明 |
---|---|---|
Vue 3 | 创建自定义指令 / 全局组件 | 自动处理所有含 Emoji 的元素 |
React | 使用全局解析函数(如 HOC 或 Layout hook) | 在渲染后全局替换 DOM 中 Emoji |
//vue 全局应用
//(用于 layout组件 或 app.vue)
<script setup>
import { onMounted } from 'vue';
import twemoji from 'twemoji';onMounted(() => {twemoji.parse(document.body, {folder: 'svg',ext: '.svg'});
});
</script>//react全局应用
//方法1 在 Layout / App.jsx 中统一解析
import React, { useEffect } from 'react';
import twemoji from 'twemoji';function App() {useEffect(() => {twemoji.parse(document.body, {folder: 'svg',ext: '.svg'});}, []);//只会在组件首次渲染(挂载)到 DOM 之后执行一次,return (<div><h1>Hello React 😄❤️🎉</h1>{/* 其他页面组件 */}</div>);
}
export default App;//方法2 创建高阶组件(HOC)包裹需要解析的组件
//接收组件 返回包装好的新组件
import twemoji from 'twemoji';
import { useEffect, useRef } from 'react';export function withTwemoji(Component) {return function Wrapped(props) {const ref = useRef();useEffect(() => {if (ref.current) {//ref.current 指的就是 useRef 返回的 ref 对象所实际引用的值twemoji.parse(ref.current, {folder: 'svg',ext: '.svg'});}}, []);return (<div ref={ref}><Component {...props} /></div>);};
}
//需要使用的组件直接使用:
const TwemojiPage = withTwemoji(MyPageComponent);
twemoji.parse() 的作用是:它会扫描传入的 DOM 元素(在这里是 ref.current 所引用的元素)内部的文本内容,找到其中的 Unicode Emoji 字符,然后将这些字符替换成 <img>
标签,而<img>
标签的 src 属性指向 Twemoji 的 SVG 图片。ref.current 这个变量本身(它存储的内存地址)没有改变,它依然指向同一个 div 元素。但这个 div 元素内部的子节点和内容被 twemoji.parse 方法修改了。
- 但vue全局应用的方法可能出现问题:没有生效
解析时 DOM 内容还没真正渲染完,App.vue 的 onMounted() 仅保证 Vue 根组件挂载,但此时子组件内容可能尚未完全渲染进 DOM;
解决方法有两种
- 用 Layout 页面来做解析(推荐用于中大型项目)
不要在 App.vue 直接解析,而是把解析放到页面 Layout 或页面组件(如 MainLayout.vue 或 HomePage.vue)中的 onMounted() 中,这样确保 Emoji 渲染后再替换
推荐在主页面区域加个 id=“main-content” 来明确定位,不要直接操作整个 document.body。
保证这个区域包裹需要解析的区域
import { onMounted, ref } from 'vue';
import twemoji from 'twemoji';onMounted(() => {const el = document.getElementById('main-content'); // 指定 DOM 区域if (el) {twemoji.parse(el, { folder: 'svg', ext: '.svg' });}
});//最好是使用nextTick 保证获取到的是最新内容
onMounted(() => {nextTick(() => {//等待 Vue 完成本轮 DOM 更新后再执行代码,确保你访问到的是已经渲染进 DOM 的最终结果。if (contentRef.value) {twemoji.parse(contentRef.value, {folder: 'svg',ext: '.svg'});}});//如果带emoji的内容是通过异步加载或父组件传入,也可能不会生效
//Vue 渲染晚于 onMounted,那 Twemoji 在执行时内容还没出现在 DOM。
//解决方法:用 watch 监听变化后再解析
import { watch } from 'vue';
watch(content, () => {nextTick(() => {twemoji.parse(emojiBox.value, { folder: 'svg', ext: '.svg' });});
});//如果内容使用了 v-html,Vue 不会触发 DOM 更新钩子,
// 则twemoji.parse 不会自动处理
- 封装成全局自定义指令(最推荐)
使用 v-twemoji 指令来保证解析的是已经渲染完的 DOM 元素
// plugins/twemoji.js
import twemoji from 'twemoji';export default {install(app) {app.directive('twemoji', {mounted(el) {twemoji.parse(el, { folder: 'svg', ext: '.svg' });},updated(el) {twemoji.parse(el, { folder: 'svg', ext: '.svg' });}});}
};
//在 App.vue、Layout.vue 或任意组件这样使用
<template><div v-twemoji>Hello 😊🎉</div>
</template>
- 部分应用
//部分应用
//vue
<template><div ref="emojiContainer">{{ message }}</div>
</template><script setup>
import { onMounted, ref } from 'vue';
import twemoji from 'twemoji';const emojiContainer = ref(null);
const message = '你好 Vue 😊❤️🎉';onMounted(() => {twemoji.parse(emojiContainer.value, {folder: 'svg',ext: '.svg'});
});
</script>//react
import React, { useEffect, useRef } from 'react';
import twemoji from 'twemoji';const EmojiText = ({ text }) => {const ref = useRef();useEffect(() => {twemoji.parse(ref.current, {folder: 'svg',ext: '.svg'});}, []);return <div ref={ref}>{text}</div>;
};export default function App() {return <EmojiText text="Hello 😄🎉 from React!" />;
}
验证
使用浏览器开发者工具,检查是否 emoji 被替换为<img>
,src来自twemoji…cdn…地址
相关文章:
【前端】Twemoji(Twitter Emoji)
目录 注意使用Vue / React 项目 验证 Twemoji 的作用: Twemoji 会把你网页/应用中的 Emoji 字符(如 😄)自动替换为 Twitter 风格的图片(SVG/PNG); 它不依赖系统字体,因此在 Android、…...

Electron 桌面程序读取dll动态库
序幕:被GFW狙击的第一次构建 当我在工位上输入npm install electron时,控制台跳出的红色警报如同数字柏林墙上的一道弹痕: Error: connect ETIMEDOUT 104.20.22.46:443 网络问题不用愁,请移步我的另外文章进行配置:…...
实时技术对比:SSE vs WebSocket vs Long Polling
早期网站仅展示静态内容,而如今我们更期望:实时更新、即时聊天、通知推送和动态仪表盘。 那么要如何实现实时的用户体验呢?三大经典技术各显神通: • SSE(Server-Sent Events):轻量级单向数据…...
js 手写promise
const PENDING pending; const FULFILLED fulfilled; const REJECTED rejected;class MyPromise {#status PENDING;#result undefined;#handler undefined;constructor(executor) {// 不能写在外面,因为this指向会出问题const resolve (data) > {this.#ch…...

HTTP 与 HTTPS 深度解析:原理、实践与大型项目应用
1. HTTP 与 HTTPS 基础概念 1.1 HTTP(超文本传输协议) 定义:应用层协议,基于 TCP/IP 通信,默认端口 80 特点: 无状态协议(需 Cookie/Session 维护状态) 明文传输(易被…...
QT6.9中opencv引用路径的其中一种设置
RC_ICONSappimage.ico unix|win32: LIBS -L$$PWD/opencv455/vc15/lib/ -lopencv_world455 INCLUDEPATH $$PWD/opencv455/include DEPENDPATH $$PWD/opencv455/include RC_ICONS为指定图标文件,只写图标名appimage.ico,那么一般和pro文件在同一目录…...
k8s pod启动失败问题排查
1. 查看日志 kubectl describe pod xxx -n xxx kubectl logs podname -n xxx --tail200 2. 镜像 到pod所在主机检查pod所需的镜像是否能成功拉取(docker images) 3.硬件资源 检查pod所在服务器的磁盘空间是否被占满(df -h 和 du -sh /&a…...
Java类中各部分内容的加载执行顺序
目录 1. 静态初始化(类加载阶段) 示例代码 输出 2. 实例初始化(对象创建阶段) 详细顺序 示例代码 输出 3. 关键规则总结 4. 注意事项 5. 完整流程图 在Java中,类的实例化过程(对象创建࿰…...
git提交信息错误,如何修改远程git提交的备注信息
有时候我们在git提交时没有按照规范提交。此时就需要修改远程git提交的备注信息。 一、修改最近几次提交 首先确保当前分支没有未提交的更改 git status使用交互式rebase修改历史记录(假设要修改最近3次提交) git rebase -i HEAD~3在打开的编辑器中&…...

API Gateway CLI 实操入门笔记(基于 LocalStack)
API Gateway CLI 实操入门笔记(基于 LocalStack) Categories: Cloud Google Rank Proof: No Last edited time: May 26, 2025 4:18 AM Status: Early draft Tags: aws 主要先简单的走一下流程,熟悉一下在 terminal 操作 API Gateway local…...
基于MATLAB实现SFA(Slow Feature Analysis,慢特征分析)算法
基于MATLAB实现SFA(Slow Feature Analysis,慢特征分析)算法的代码示例: % SFA慢特征分析 % 需要signal处理工具箱% 生成示例信号 t linspace(0,1,1000); x sin(2*pi*10*t) sin(2*pi*20*t) randn(size(t));% 定义滤波器 b fi…...

数据分析案例-基于红米和华为手机的用户评论分析
🤵♂️ 个人主页:艾派森的个人主页 ✍🏻作者简介:Python学习者 🐋 希望大家多多支持,我们一起进步!😄 如果文章对你有帮助的话, 欢迎评论 💬点赞Ǵ…...
leetcode617.合并二叉树:递归思想下的树结构融合艺术
一、题目深度解析与核心规则 题目描述 合并两棵二叉树是一个经典的树结构操作问题,题目要求我们将两棵二叉树合并成一棵新二叉树。合并规则如下: 若两棵树的对应节点都存在,则将两个节点的值相加作为新节点的值若其中一棵树的节点存在&…...

深度学习入门:从零搭建你的第一个神经网络
深度学习入门:从零搭建你的第一个神经网络 系统化学习人工智能网站(收藏):https://www.captainbed.cn/flu 文章目录 深度学习入门:从零搭建你的第一个神经网络摘要引言第一章:神经网络基础原理1.1 神经元…...
【HTML-13】HTML表格合并技术详解:打造专业数据展示
表格是HTML中展示结构化数据的重要元素,而表格合并则是提升表格表现力的关键技术。本文将全面介绍HTML中的表格合并方法,帮助您创建更专业、更灵活的数据展示界面。 1. 表格合并基础概念 在HTML中,表格合并主要通过两个属性实现:…...
鸿蒙OSUniApp 制作自定义的进度条组件#三方框架 #Uniapp
使用 UniApp 制作自定义的进度条组件 在移动应用开发中,进度条是非常常见的 UI 组件,无论是文件上传、下载、任务进度还是表单填写反馈,进度条都能为用户提供直观的进度提示。虽然 UniApp 提供了一些基础的进度条能力,但在实际项…...

【Python办公】Excel简易透视办公小工具
目录 专栏导读1. 背景介绍2. 功能介绍3. 库的安装4. 界面展示5. 使用方法6. 实际应用场景7. 优化方向完整代码总结专栏导读 🌸 欢迎来到Python办公自动化专栏—Python处理办公问题,解放您的双手 🏳️🌈 博客主页:请点击——> 一晌小贪欢的博客主页求关注 👍 该系…...
m1 运行renrenfastvue出现的问题和解决方案
1. chromedriver 报错解决:执行 npm install --ignore-scripts。 2. node-sass 报错 "Node Sass does not yet support your current environment: OS X Unsupported ...": - 降低 Node 版本至 14。 - 安装版本控制工具:sudo npm insta…...
开源模型应用落地-qwen模型小试-Qwen3-8B-推理加速-vLLM-Docker(二)
一、前言 在AI模型部署效率竞争日益激烈的当下,如何将前沿大模型与高效推理框架结合,成为开发者关注的焦点。Qwen3-8B作为阿里云推出的混合推理模型,凭借80亿参数规模与128K超长上下文支持,展现了“快思考”与“慢思考”的协同能力,而vLLM框架则通过优化内存管理与并行计算…...
【C/C++】记录一次麻烦的Kafka+Json体验
文章目录 麻烦的KafkaJson体验1 目标2 工程搭建2.1 docker配置2.2 代码2.3 工程压缩包 3 执行结果 麻烦的KafkaJson体验 1 目标 初心:结合kafka json docker,验证基本的数据生产/消费。 Kafka 配合 JSON 工具,主要是为了数据的序列化和反…...

Linux系列-2 Shell常用命令收集
背景 本文用于收集Linux常用命令(基于Centos7),是一个持续更新的博客,建议收藏,编写shell时遇到问题可以随时查阅。 1.Shell类型 shell是用C语言编写的程序,作为命令解释器连接着用户和操作系统内核。常见的shell有sh(Bourne She…...

MATLAB使用多个扇形颜色变化表示空间一个点的多种数值
MATLAB使用多个扇形颜色变化表示空间一个点的多种数值 excel中表格中数据格式,多行 lonlatdata1data2data3117380.11100 clear;close all; figure(Position,[100 100 800 800]);num_points 14; [num,txt,raw] xlsread(test.xlsx); x num(:,1); y num(:,2);d…...
mysql:MVCC机制
MVCC机制 MVCC机制主要是mysql的多版本并发控制的一个机制,它主要是允许mysql去保存同一时间对同一份数据的不同历史版本的,从而避免读写之间的锁竞争,从而去提高并发的性能。 像传统的锁机制(读写互斥锁(Read-Write …...
Vue3 + Element Plus 实现树形结构的“单选 + 只选叶子节点 + 默认选中第一个子节点”
在 Vue 项目中,我们常使用树形结构组件来展示层级数据。本文将介绍如何使用 Element Plus 的 <el-tree> 组件,在 Vue3 中实现以下需求: ✅ 只能勾选叶子节点 ✅ 每次只能选中一个节点(单选) ✅ 页面加载时默认…...

CAD精简多段线顶点、优化、删除多余、重复顶点——CAD c#二次开发
附部分代码如下: public static void Pl精简(){Document doc Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument;Database db doc.Database;Editor ed doc.Editor;var plOrigon db.SelectCurve("\n选择多段线:");…...

输电线路的“智慧之眼”:全天候可视化监测如何赋能电网安全运维
在电力需求持续攀升、电网规模日益庞大的今天,输电线路的安全稳定运行面临着前所未有的挑战。线路跨越地形复杂多变,尤其是在偏远山区、铁路沿线及恶劣天气条件下,传统的人工巡检方式显得力不从心——效率低、风险高、覆盖有限。如何实现更智…...
Spring 核心知识点补充
Spring 核心知识点补充 1. IoC(控制反转) 核心思想:将对象的创建和依赖管理交给容器,而非在代码中直接控制实现方式: XML 配置:<bean> 标签定义对象注解:Component, Service, Repositor…...

两阶段法目标检测发展脉络
模式识别期末展示大作业,做个记录,希望大家喜欢。 R-CNN Fast R-CNN R-FCN 整个过程可以分解为以下几个步骤: 输入图像 (image) 和初步特征提取 (conv, feature maps): 首先,输入一张原始图像,经过一系列…...
Flannel 支持的后端
Flannel 是一个为 Kubernetes 设计的容器网络解决方案,支持多种后端(backend)来处理节点间的数据包转发。根据官方文档和其他可靠来源,以下是 Flannel 支持的后端类型及其说明: VXLAN(推荐) 描述…...

小白的进阶之路系列之六----人工智能从初步到精通pytorch数据集与数据加载器
本文将介绍以下内容: 数据集与数据加载器 数据迁移 如何建立神经网络 数据集与数据加载器 处理数据样本的代码可能会变得混乱且难以维护;理想情况下,我们希望我们的数据集代码与模型训练代码解耦,以获得更好的可读性和模块化。PyTorch提供了两个数据原语:torch.utils…...