【问题标题】:Javascript extract anchor tag from a string and create new React component from itJavascript 从字符串中提取锚标记并从中创建新的 React 组件
【发布时间】:2021-05-21 18:30:34
【问题描述】:

我正在使用 React 和 Javascript,并且有一个要求,我需要提取某些锚标记,获取它们的属性,如 id、href 并从中创建一个自定义的 React 链接组件。 我的字符串看起来像这样 "<p>Bla bla bla bla.</p>\n<ul>\n<li><strong>Bla bla</strong>. Bla bla bla.</li>\n<li><strong>Bla bla bla</strong>.<a href='#footnote1' id='sup1'><sup>1</sup></a> Bla bla bla.</li>\n<li><strong>Bla bla bla.<a href='#footnote2' id='sup2'><sup>2</sup></a>\r\n</strong>  Bla bla bla.</li>\n<li><strong>Bla bla:</strong>Bla bla <a href=\"https://google.com\" target=\"no\">Google</a> * bla bla bla.<a href='#footnote1' id='sup3'><sup>1</sup></a></li>\n</ul>\n<p> </p>"

我只想提取其中包含<sup> 的所有<a>。然后我想获取此类<a> 的属性并创建一个自定义的 React 链接组件,例如

<MyLink
      id={id of the anchor tag}
      addClasses={"footnote-link"}
      href={href of anchor tag}
      handleClick={myClickHandler}
      ariaProps={{
        label: {text inside the sup tag}
      }}
    >
      <sup className={href of anchor tag !== null ? "custom-class" : ""}>{text inside the sup tag}</sup>
    </MyLink>

然后我想用字符串中的自定义组件替换那些&lt;a&gt;。我试图将&lt;a&gt; 转换为自定义组件的原因是我希望新的锚标记符合 A11Y 并且锚标记和源字符串不在我的控制范围内。

我尝试了How to get the href value of an anchor tag with javascript from a stringjavascript regex to extract anchor text and URL from anchor tags 的组合,但没有取得太大进展。 我也试过react-string-replace,但也没多大帮助。

我还可以选择将&lt;a href='#footnote1' id='sup1'&gt;&lt;sup&gt;1&lt;/sup&gt;&lt;/a&gt; 替换为#FootNote({id:\"sup1-CB\", goto:\"sup1\", data:\"1\"})#FootNote 之类的东西,然后使用“id”、“goto”和“data”来创建自定义链接。

谁能提供一些关于如何实现这一目标的指导? 对于这个冗长的问题,我深表歉意。

【问题讨论】:

标签: javascript reactjs


【解决方案1】:

这里有一个例子,它使用创建的标签来解析你的 html,然后使用 DOM 方法来提取你需要的数据:

const str =
  "<p>Bla bla bla bla.</p>\n<ul>\n<li><strong>Bla bla</strong>. Bla bla bla.</li>\n<li><strong>Bla bla bla</strong>.<a href='#footnote1' id='sup1'><sup>1</sup></a> Bla bla bla.</li>\n<li><strong>Bla bla bla.<a href='#footnote2' id='sup2'><sup>2</sup></a>\r\n</strong>&#160; Bla bla bla.</li>\n<li><strong>Bla bla:</strong>Bla bla <a href=\"https://google.com\" target=\"no\">Google</a> * bla bla bla.<a href='#footnote1' id='sup3'><sup>1</sup></a></li>\n</ul>\n<p>&#160;</p>";

const el = document.createElement("html");
el.innerHTML = str;
const anchors = el.getElementsByTagName("a");

const MyLink = () => null;
const myClickHandler = () => null;

export default () =>
  [...anchors].map((anchor, index) => {
    const sup = anchor.getElementsByTagName("sup");
    if (sup.length === 0) {
      return null;
    }

    return (
      <MyLink
        key={index.toString()}
        id={anchor.id}
        addClasses={"footnote-link"}
        href={anchor.href}
        handleClick={myClickHandler}
        ariaProps={{
          label: sup[0].innerHTML
        }}
      >
        <sup className={anchor.href ? "custom-class" : ""}>{sup[0].innerHTML}</sup>
      </MyLink>
    );
  });


MyLinkmyClickHandler 替换为您自己的。

【讨论】:

  • 这很有帮助。谢谢!它可以帮助我用我的自定义链接组件替换锚标记。但是,我还需要在浏览器上显示源字符串(以及所有 p、ul、li 等),并用我的自定义链接替换锚标记。页面渲染一次后,我是否应该在此处使用 useEffect() 用新字符串(即用自定义链接替换的锚点)更新 DOM?
  • 同样的方法也可以用来提取ulli节点。它的复杂性取决于源结构的动态程度。
  • 您的反应很快。在那之后我编辑了我的最后一个回复。我不是要提取 ul, li。在用自定义链接替换锚标记后,我试图在浏览器上呈现我的源字符串

    bla bla

    • ....。我希望我说得通。
【解决方案2】:

您可以考虑解析 HTML 并使用 DOM 方法对其进行修改,然后将其呈现为字符串。下面的演示只是一个概念证明,但它可以被合并到一个做同样事情的 React 组件中。

注意:这类似于Dean's answer,后者有一个更特定于 React(并且可以说更简洁)的示例。

const input = "<p>Bla bla bla bla.</p>\n<ul>\n<li><strong>Bla bla</strong>. Bla bla bla.</li>\n<li><strong>Bla bla bla</strong>.<a href='#footnote1' id='sup1'><sup>1</sup></a> Bla bla bla.</li>\n<li><strong>Bla bla bla.<a href='#footnote2' id='sup2'><sup>2</sup></a>\r\n</strong>&#160; Bla bla bla.</li>\n<li><strong>Bla bla:</strong>Bla bla <a href=\"https://google.com\" target=\"no\">Google</a> * bla bla bla.<a href='#footnote1' id='sup3'><sup>1</sup></a></li>\n</ul>\n<p>&#160;</p>"

const parser = new DOMParser();

const doc = parser.parseFromString(input, 'text/html');

// might be a more efficient way to do this. just querying for anchors
// and filtering out the ones that don't have a <sup> child
const anchors = [...doc.querySelectorAll('a')].filter(elem => elem.querySelector('sup'));

anchors.forEach(a => {
  const sup = a.querySelector('sup');
  a.setAttribute('aria-label', sup.innerText);
  // etc.
})

document.getElementById('demo').innerHTML = doc.body.innerHTML;
document.getElementById('source').innerText = doc.body.innerHTML;
<h2>Resulting html</h2>
<pre id="source"></pre>

<hr/>

<h2>Rendered result</h2>
<div id="demo"></div>

【讨论】:

  • 谢谢@ray-hatfield!这个解决方案看起来也很有希望,但问题是我不想只向锚标记添加一些属性。我想用我在问题中描述的自定义 React 链接组件完全替换这些锚标签。
  • 明白。这并不是一个完整的解决方案,只是指路。使用 Document/DOM 将使提取您需要的任何信息变得比字符串操作更容易、更不容易出错。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-01-21
  • 2021-05-22
  • 2016-06-27
  • 1970-01-01
相关资源
最近更新 更多