
本文介绍如何在 react 中实时动态替换模板字符串(如 `”hello ${firstname} ${lastname}”`)中的占位符,支持任意数量的变量,避免因更新顺序导致的覆盖问题。
在构建表单驱动的模板编辑器(如邮件模板、消息生成器)时,一个常见需求是:用户在输入框中修改字段(如 firstName、lastName),页面上预览的模板文本需即时、准确地同步更新所有对应占位符。难点在于——不能仅依赖“最后修改的字段”去替换,而应基于当前完整数据状态对整个模板进行全量、安全、可扩展的替换。
下面是一个健壮、可扩展的实现方案:
✅ 核心思路
- 将所有可替换变量统一管理为一个对象状态(如 { firstName: ”, lastName: ”, email: ” }),便于动态增删字段;
- 使用 useEffect 监听该对象的变更,每次变化后遍历所有键名,对模板字符串执行 .replace() 替换(注意:需全局替换,避免只替换首个匹配项);
- 为防止正则特殊字符干扰或误替换,采用字符串字面量拼接方式构造占位符(如 “${” + key + “}”),而非正则表达式,确保语义清晰、行为可控。
✅ 完整可运行代码(支持 N 个变量)
import { useState, useEffect } from "react"; export default function TemplateEditor() { // ✅ 可扩展的数据源:新增字段只需在此对象中添加键值对 const [data, setData] = useState({ firstName: "", lastName: "", email: "", company: "" }); // ✅ 原始模板(支持任意数量的 ${key} 占位符) const [template, setTemplate] = useState( "Hi ${firstName} ${lastName}, welcome to ${company}! Contact us at ${email}." ); // ✅ 实时渲染的最终文本 const [preview, setPreview] = useState(template); // ✅ 统一处理输入事件 const handleInputChange = (e) => { const { name, value } = e.target; setData((prev) => ({ ...prev, [name]: value })); }; // ✅ 关键逻辑:当 data 变化时,全量重写 preview useEffect(() => { let result = template; Object.keys(data).forEach((key) => { const placeholder = "${" + key + "}"; // ⚠️ 注意:replace() 默认只替换第一个匹配项,需用 replaceAll() 或正则全局标志 result = result.replaceAll(placeholder, data[key]); }); setPreview(result); }, [data, template]); return ( ? 模板预览
{preview}
✏️ 编辑字段
{Object.keys(data).map((key) => (
))}