用 JSX 中的 HTML 跨度节点替换字符串中的花括号

Posted

技术标签:

【中文标题】用 JSX 中的 HTML 跨度节点替换字符串中的花括号【英文标题】:Replace Curly Braces in string with a HTML span Node in JSX 【发布时间】:2017-01-03 12:00:06 【问题描述】:

我有一个字符串需要参数化,例如“你好 name,你好吗?”。我想用一个变量替换花括号和里面的文本,然后在我的 React 组件中呈现它,但我还需要通过将变量文本包装在 span/strong 标签中来突出显示和加粗该文本,例如期望的最终结果

Hello <span class="text-info"><strong>Dave</strong></span>, how are you?

我正在使用 React/JSX,我知道如何使用 String.replace 替换花括号和其中的文本,然后渲染它,例如

// This string with the placeholder curly braces would be received from an API call to a server. Only set here for demonstrative purposes
let string = 'Hello name, how are you?' 
let name = 'Dave' // Likewise would not be set manually here, it's held in a redux store
let greeting = string.replace(/(.*?)/, name);

// This renders the greeting as you'd expect e.g. <p>Hello Dave, how are you?</p>
return (
   <p>greeting</p>
)

但是,如果我尝试用 span 元素替换花括号,它会错误地使用 [object Object] 而不是我的参数呈现

// ...rest of stateless Component.jsx
let greeting = string.replace(/(.*?)/, <span>name</span>);

// This renders the html <p>Hello [object Object], how are you?</p>
return (
   <p>greeting</p>
)

我认为这一定与 React 逃避某些东西有关,但老实说,这完全是猜测。有什么想法可以实现所需的功能吗?

JSFiddle:https://jsfiddle.net/ExoticChimp1990/o69ymt7q/

【问题讨论】:

您使用 String.replace 而不做这样的事情有什么原因吗? jsfiddle.net/e851a1ua 这是因为字符串和名称变量来自服务器的单独调用。所以名称保存在用户对象的 redux 存储中。并且文本也使用占位符存储在数据库中的服务器上。所以我需要用商店的用户信息替换占位符。问题澄清 转译后,&lt;span&gt;name&lt;/span&gt; 将被替换为返回对象的React.createElement("span", null,name) 的结果,这就是结果字符串显示为[object Object] 的原因。 @user1858268 是的,我认为可能会发生类似的事情,您知道实现所需功能的任何替代策略吗? 你可以替换为"&lt;span&gt;" + name + "&lt;/span&gt;",然后使用setInnerHtml进行渲染。但可能还有其他方法。 【参考方案1】:

您可以尝试用包含原始 html 标记的字符串替换,然后使用 dangerouslySetInnerHTML 渲染您的 div。

var greeting = textToEnhance.replace(/(.*?)/, '<span>'+this.props.name+'</span>'); 

return <div dangerouslySetInnerHTML=__html:greeting></div>;

【讨论】:

是的,我想过尝试使用危险的SetInnerHTML,但我不确定安全隐患是什么?【参考方案2】:

顺便说一句,您可以使用 ES6 的格式,例如

const name = "David";
const myHTML = `Hello $name, how are you?`;

注意:这些不是单引号,而是`符号。这个符号称为“重音”字符

我了解您的模板来自服务器,因此您不能直接使用上述方法。

但是,使用诸如 /\$\(\w+?)\/g 之类的 RegExp(单击此 RegExp 过期),您可以解析和遍历所有变量名称,例如

var newString = templateString.replace(/(\$\\w+?\)/g, function(match, p1, offset, str) 
  var matches = /\$\(\w+?)\/.exec(p1);
  var variableName = matches[1];
  return variables[variableName]
    ?variables[variableName]
    :console.error("Variable " + variableName + " is undefined in offset " + offset);
);

variables 是一个预定义的对象,其中包含您的变量作为键值对并且 templateString 包含您的模板(可选地来自服务器)。

【讨论】:

【参考方案3】:

您在 string.replace 中使用的第二个参数不正确。大括号内的 name 变量表示,一个 javascript 对象,其 name 键和值与 name 变量中的一样。

let greeting = string.replace(/(.*?)/, '<span><strong>'+name+'</strong></span>');

对不起,因为我没有输入上面的字符串作为代码,它省略了标签。现在它们必须是可见的。

【讨论】:

不,那不是真的。如果您检查小提琴,您可以看到注释掉的答案工作正常。这并不能回答我的问题,本质上是我想将变量包装在跨度标签中 如果您检查来自 user1858268 的答案,您仍然需要使用危险设置的内部 HTML 来使用它

以上是关于用 JSX 中的 HTML 跨度节点替换字符串中的花括号的主要内容,如果未能解决你的问题,请参考以下文章

如何在节点中的文本中替换/注入html标签?

用JSON字符串中的布尔值替换字符串?

用 HTML 表示文档 DOM:兄弟文本节点

替换后innerHTML不呈现

如果字段有信息,如何显示跨度,否则 React JSX 不显示?

Webpack 无法识别节点模块中的 jsx 代码