用反应中的html标签替换字符串之间的字符

时间:2016-10-21 19:16:39

标签: javascript html reactjs

我试图解析一些文字,以便_this is emphasized!_包含在<em>标记中,如下所示:<em>this is emphasized!</em>

我的组件目前看起来像这样:

export default class TextParser extends React.Component {
  render() {
    let text = this.props.text,
        parsed, regex, paragraphs;

    regex = {
      paragraph: /(?:\r\n){2,}/g,
      emphasize: /\_(.*?)\_/g,
      strong: /\*(.*?)\*/g,
    }

    // Apply regex
    text = text.replace(regex.emphasize, (str) => {
      let parsed = str.substr(1, str.length - 1);

      return ('<em>' + parsed + '</em>')
    })

    paragraphs = text.split(regex.paragraph) || []
    paragraphs = paragraphs.map((text, i) => {
      return (
        <p key={i}>
          {text}
        </p>
      )
    })

    return (
      <div className="document">{paragraphs}</div>
    )
  }
}

这不起作用,但输出html以纯文本显示标签,而不是在html中使用它们。这当然是因为消毒。

我可以dangerouslySetInnerHTML但我想避免这种情况。如何使用<em>标记替换文本之间的下划线?

1 个答案:

答案 0 :(得分:2)

正如您所注意到的那样,将字符串"<em>"作为replace结果的一部分,只会添加该字符串而不是实际标记。

您无法直接在replace内创建标记,因为它在字符串上运行。

相反,将字符串分解为单独的元素,并将标记添加到您需要的位置。你已经在段落案例中做了类似的事情。

因为段落大小写也适用于字符串,所以这些操作只能嵌套,因为一旦完成操作,就不再有纯文本字符串,而是有一个对象数组。所以在这个例子中,我在段解析中移动了<em>解析。

最后一点,我必须修改emphasize的正则表达式,以便它捕获下划线,因为我需要在完成拆分后再次检查它是否匹配。

let text = this.props.text,
    parsed, regex, paragraphs;

regex = {
  paragraph: /(?:\r\n){2,}/g,
  emphasize: /(\_.*?\_)/g,
  strong: /\*(.*?)\*/g,
}

paragraphs = text.split(regex.paragraph) || []
paragraphs = paragraphs.map((text, i) => {
  return (
    <p key={i}>
      {        
           // Apply regex
           text.split(regex.emphasize).map((str) => {
           let parsed = str.search(regex.emphasize) !== -1 
              ? (<em>{str.substr(1, str.length - 2)}</em>) 
              : str;
            return parsed;
        })}
    </p>
  )
})

return (
  <div className="document">{paragraphs}</div>
)

根据您在下面的评论,您还想知道如何处理/或格式化案例。所以为了完整性,我在这里包含了代码。我选择将格式化模式合并为一个正则表达式,然后我明确检查“_”或“*”以决定是添加em还是b标记。然后我会在匹配时递归调用它,以防其中有其他匹配。您可以选择以不同的方式清理它,但我希望这会有所帮助。

let text = this.props.text,
    parsed, regex, paragraphs;

regex = {
  paragraph: /(?:\r\n){2,}/g,
  formatting: /(\_.*?\_)|(\*.*?\*)/g,
}

  let applyFormatting = (text) => {
    return text.split(regex.formatting).filter(n => n).map((str) => {
    let parsed = str[0] == '_'
        ? (<em>{applyFormatting(str.substr(1, str.length - 2))}</em>)
        : str[0] == '*'
        ? (<b>{applyFormatting(str.substr(1, str.length - 2))}</b>)
        : str;
    return parsed;
  });
};

paragraphs = text.split(regex.paragraph) || []
paragraphs = paragraphs.map((text, i) => {
  return (
    <p key={i}>
      { applyFormatting(text) }
    </p>
  )
})

return (
  <div className="document">{paragraphs}</div>
)