【问题标题】:JSX Component + dangerouslySetInnerHTML?JSX 组件 + 危险的 SetInnerHTML?
【发布时间】: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 上实现的东西,但我不知道从哪里开始。

【问题讨论】:

    标签: javascript regex reactjs react-dom


    【解决方案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(/(&lt;li&gt;.*?&lt;\/li&gt;)/g) 匹配数组中 html 字符串中的每个 &lt;li&gt;...&lt;/li&gt;,然后可以映射。然后我使用捕获(括号内的部分)从每个&lt;li&gt;...&lt;/li&gt; 中提取标题、href 等,然后可以在 JSX 中使用。 This answer 提供了有关使用的正则表达式的更多详细信息。

    【讨论】:

      【解决方案2】:

      不幸的是,我从未真正使用过 JavaScript,这就是为什么我的答案将只关注这个问题的正则表达式部分。 (不过,我在底部添加了一个尝试!)

      如果我理解正确,您想用&lt;ModalLink href={'someLink'}&gt;someTitle&lt;/ModalLink&gt; 替换&lt;a href="someLink"&gt;someTitle&lt;/a&gt; 标记,使someLinksomeTitle 也出现在ModalLink 标记中 - 请纠正我我以错误的方式理解这一点

      现在看看这里的正则表达式模式

      <a [^<]+?href\s*=\s*("|')(.*?)\1>(.*?)<\/a>
      

      它将匹配以&lt;a 开头的任何标记并匹配所有字符,直到找到href(在href 和等式标记之间有任意数量的空格)。然后它将搜索''"" 引号之间的字符串并捕获它以便以后使用。它再次匹配,直到找到标记 &gt; 的结尾并捕获该结尾和结束标记 &lt;\a&gt; 之间的任何内容。

      如果您现在使用某种方法来替换给定字符串中匹配的正则表达式(很抱歉,我不熟悉这在 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 当然应该是要替换 &lt;a&gt; 标记的 html 字符串。

      你也可以试试this online here

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2019-04-26
        • 1970-01-01
        • 1970-01-01
        • 2021-01-23
        • 2019-06-18
        • 2021-01-30
        • 2021-07-24
        • 1970-01-01
        相关资源
        最近更新 更多