当前位置: 首页 > ds >正文

【前端】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; /* 调整与文字基线对齐 */
}

使用

  1. CDN引入
<script src="https://twemoji.maxcdn.com/v/latest/twemoji.min.js"></script>
  1. 在页面加载后执行解析
<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;
    解决方法有两种
  1. 用 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 不会自动处理
  1. 封装成全局自定义指令(最推荐)
    使用 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…地址

http://www.xdnf.cn/news/9956.html

相关文章:

  • RV1126-OPENCV Mat理解
  • 某东 h5st第8个参数 指纹加密纯算解析
  • 模型微调之对齐微调KTO
  • MySQL的binlog有有几种录入格式分别有什么区别 ?
  • VSCode的下载与安装(2025亲测有效)
  • LLaMaFactory 微调QwenCoder模型
  • Windows 中禁止在桌面放置文件以保持桌面整洁
  • 深入详解编译与链接:翻译环境和运行环境,翻译环境:预编译+编译+汇编+链接,运行环境
  • does not provide an export named ‘getActiveHead‘
  • 集成均衡功能电池保护芯片在大功率移动电源的应用,创芯微CM1341-DAT、杰华特JW3312、赛微微电CW1244、中颖SH366006
  • 从Homebrew找到openssl.cnf文件并拷贝到Go项目下使用
  • vr中风--数据处理模型搭建与训练
  • NW907NW918美光固态闪存NW920NW930
  • mongodb删除字段
  • springboot拦截器的基本配置
  • lost connection to mysql server at ‘reading initial communication packet‘
  • 怒更一波免费声音克隆和AI配音功能
  • MediaMtx开源项目学习
  • window 显示驱动开发-转换 Direct3D 固定函数状态(二)
  • 《深度搜索-R1-0528》
  • git仓库服务gogs详解
  • EfficMultiCoreMemoryPool项目
  • Git 中移除已追踪的文件
  • 解决 xmlsec.InternalError: (-1, ‘lxml xmlsec libxml2 library version mismatch‘)
  • TensorFlow深度学习实战(18)——K-means 聚类详解
  • QML视图组件ListView、TableView、GridView介绍
  • 人工智能-训练AI模型涉及多个步骤
  • 数据结构(7)树-二叉树-堆
  • uni-app 安卓消失的字符去哪里了?maxLength失效了!
  • 2025年DDoS混合CC攻击防御全攻略:构建智能弹性防护体系