JSX 组件 + 危险的 SetInnerHTML?
Posted
技术标签:
【中文标题】JSX 组件 + 危险的 SetInnerHTML?【英文标题】:JSX Component + dangerouslySetInnerHTML? 【发布时间】:2018-04-30 19:17:25 【问题描述】:所以我在实现这个场景时遇到了麻烦:
从后端服务器,我收到一个 html 字符串,如下所示:
<ul><li><strong>Title1</strong> <br/> <a class=\"title1" href="title1-link">Title 1</a></li><li><strong>Title2</strong> <a class="title2" href="/title2-link">Title 2</a>
通常,只使用dangerouslySetInnerHTML
就可以了。
但是,围绕 html 中的 a href
标签,我需要将它们包装在组件中,如下所示:
<ModalLink href='title'>
Title
</ModalLink>
这是因为在包装a
标签时,组件本质上添加了创建新子窗口的功能。
我认为这是你需要在 Regex 上实现的东西,但我不知道从哪里开始。
【问题讨论】:
【参考方案1】:您可以使用正则表达式从您的 html 字符串中解构和提取必要的值,然后使用 JSX 代替危险的SetInnerHtml。该组件展示了如何呈现您的示例 html 字符串。
import React, Component from 'react'
export default class App extends Component
render()
const html = `<ul><li><strong>Title1</strong><br/><a class="title1" href="/title1-link">Title 1</a></li><li><strong>Title2</strong><br/><a class="title2" href="/title2-link">Title 2</a></li></ul>`
return (
<div>
<ul>
html.match(/(<li>.*?<\/li>)/g).map( li =>
const title = li.match(/<strong>(.*?)<\/strong>/)[1]
const aTag = li.match(/<a.*?\/a>/)[0]
const aClass = aTag.match(/class="(.*?)"/)[1]
const href = aTag.match(/href="(.*?)"/)[1]
const aText = aTag.match(/>(.*?)</)[1]
return (
<li>
<strong>title</strong>
<br/>
<a className=aClass href=href>aText</a>
</li>
)
)
</ul>
</div>
)
从那里您可以简单地将 a 标签包装在您的 ModalLink 组件中。我不确定这正是您想要的方式,但这里有一个示例。
return (
<li>
<strong>title</strong>
<br/>
<ModalLink href=href>
<a className=aClass href=href>aText</a>
</ModalLink>
</li>
)
html.match(/(<li>.*?<\/li>)/g)
匹配数组中 html 字符串中的每个 <li>...</li>
,然后可以映射。然后我使用捕获(括号内的部分)从每个<li>...</li>
中提取标题、href 等,然后可以在 JSX 中使用。 This answer 提供了有关使用的正则表达式的更多详细信息。
【讨论】:
【参考方案2】:不幸的是,我从未真正使用过 javascript,这就是为什么我的答案将只关注这个问题的正则表达式部分。 (不过,我在底部添加了一个尝试!)
如果我理解正确,您想用<ModalLink href='someLink'>someTitle</ModalLink>
替换<a href="someLink">someTitle</a>
标记,使someLink
和someTitle
也出现在ModalLink 标记中 - 请纠正我我以错误的方式理解这一点
现在看看这里的正则表达式模式
<a [^<]+?href\s*=\s*("|')(.*?)\1>(.*?)<\/a>
它将匹配以<a
开头的任何标记并匹配所有字符,直到找到href
(在href 和等式标记之间有任意数量的空格)。然后它将搜索''
或""
引号之间的字符串并捕获它以便以后使用。它再次匹配,直到找到标记 >
的结尾并捕获该结尾和结束标记 <\a>
之间的任何内容。
如果您现在使用某种方法来替换给定字符串中匹配的正则表达式(很抱歉,我不熟悉这在 JavaScript 中的工作方式)并用此模式替换它
<ModalLink href='$2'> $3 </ModalLink>
对于您收到的示例 html 字符串,您将得到如下结果:
<ul><li><strong>Title1</strong> <br/> <ModalLink href='title1-link'> Title 1 </ModalLink></li><li><strong>Title2</strong> <ModalLink href='/title2-link'> Title 2 </ModalLink>
替换模式的 $2 和 $3 部分是前面提到的捕获部分的占位符,如您所见,它们将被它们替换。 (他们正在捕获第 2 组和第 3 组,而不是从 1 开始,因为我已经将引号捕获为捕获第 1 组)
你可以试试我提供的模式here。
虽然您可以在窗口上部查看和编辑正则表达式和字符串输入,但在下部可以找到替换模式及其结果。
编辑:我现在已经尽力使用在线编译器来使用 JavaScript 方法将标签替换为标签,并且在使用上述正则表达式的这种方法时似乎可以正常工作:
var regexMatch = html.replace(/<a [^<>]+?href\s*=\s*("|')(.*?)\1[^<>]*?>(.*?)<\/a>/g, "<ModalLink href='$2'> $3 </ModalLink>");
在这种情况下,html
当然应该是要替换 <a>
标记的 html 字符串。
你也可以试试this online here。
【讨论】:
以上是关于JSX 组件 + 危险的 SetInnerHTML?的主要内容,如果未能解决你的问题,请参考以下文章
在没有危险的SetInnerHTML的情况下在字符串上添加标记