You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React中如何将contentEditable占位符替换为渲染后的FontAwesome组件?

解决可编辑Div中FontAwesome表情占位符替换问题

问题场景

我在使用contentEditable的Div时,希望将输入内容中类似#fa-face-smile#的占位符替换为FontAwesome表情图标。当前代码逻辑是插入占位符后,通过convertEmoticons函数尝试替换,但实际页面显示为,[object object],,完全不符合预期。

我的可编辑Div代码:

<div
    contentEditable="true"
    ref={newMessageRef}
    className={`form-control ${errors.message ? 'is-invalid' : ''}`}
    data-raw=""
    onBlur={e => setNewEditableContent(e.target.textContent)}
/>

输入示例:

I would be so happy if #fa-face-smile# would be converted to the actual emoticon

预期替换结果对应的组件:

<FontAwesomeIcon size="2x" icon="fa-solid fa-face-smile" />

当前的转换及设置函数:

function convertEmoticons(string) {
    let replacedText = string
        .split(new RegExp(/\#(.*?)\#/, "gi"))
        .map((node, i) => (i % 2 ? <FontAwesomeIcon style={{color: '#a70000'}} size="2x" icon={getEmoticon(node)}/> : node));
    return (replacedText);
}

const _setMessageText = (text) => {
    newMessageRef.current.setAttribute("data-raw", text);
    newMessageRef.current.textContent = convertEmoticons(text);
}

错误原因

  1. convertEmoticons返回的是React元素与字符串混合的数组,直接赋值给textContent时,React元素会被强制转换为字符串[object Object]。
  2. 数组转字符串时,默认会用逗号分隔元素,所以出现了前后带逗号的情况。
  3. textContent只能设置纯文本,无法识别React组件或HTML标签。

解决方案

要实现占位符转图标,需要将转换后的内容以HTML形式插入可编辑Div,有两种可行方案:

方案1:将React组件转为静态HTML字符串

利用ReactDOMServer.renderToStaticMarkup把FontAwesomeIcon组件转为对应的HTML字符串,再拼接成完整内容后设置到innerHTML。

步骤:

  1. 导入ReactDOMServer:
import ReactDOMServer from 'react-dom/server';
  1. 修改convertEmoticons函数:
function convertEmoticons(string) {
    return string
        .split(new RegExp(/\#(.*?)\#/, "gi"))
        .map((node, i) => {
            if (i % 2 === 1) {
                // 将React组件转为HTML字符串
                const iconComponent = <FontAwesomeIcon style={{color: '#a70000'}} size="2x" icon={getEmoticon(node)}/>;
                return ReactDOMServer.renderToStaticMarkup(iconComponent);
            }
            // 纯文本部分转义,避免HTML注入
            return node.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
        }).join(''); // 数组转字符串,去掉默认逗号分隔
}
  1. 修改_setMessageText,使用innerHTML而非textContent:
const _setMessageText = (text) => {
    newMessageRef.current.setAttribute("data-raw", text);
    newMessageRef.current.innerHTML = convertEmoticons(text);
}

方案2:直接构建FontAwesome的HTML标签

跳过React组件,直接根据占位符生成FontAwesome对应的<i>标签字符串,这种方式更轻量,不需要依赖ReactDOMServer。

修改convertEmoticons函数:

function convertEmoticons(string) {
    return string.replace(/\#(.*?)\#/gi, (match, iconName) => {
        // 假设getEmoticon返回完整的类名,比如"fa-solid fa-face-smile"
        const fullIconClass = getEmoticon(iconName);
        return `<i class="${fullIconClass}" style="color:#a70000; font-size:2em"></i>`;
    });
}

同样修改_setMessageText使用innerHTML即可。

额外注意事项

  • 处理纯文本时要做HTML转义,避免用户输入的特殊字符破坏页面结构。
  • 替换后如果需要保留光标位置,需要重新计算并设置光标,可在_setMessageText末尾添加光标定位逻辑。

内容的提问来源于stack exchange,提问作者Yolo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.21 18:55:00