0

我想通过用 React 组件(即和)替换特定标签(例如<p>和)来呈现一大块 html<a><StyledParagraph><StyledLink>

我测试了许多库,包括 html-react-parser。与许多其他人不同,html-react-parser 有一个满足我需求的示例。但是,我无法让这个例子起作用。(使用反应 16.5.3)

const test = () =>
  <>
    {parse(
      `
      <p id="main">
        <span class="prettify">
          keep me and make me pretty!
        </span>
      </p>
    `,
      {
        replace: ({ attribs, children }) => {
          if (!attribs) return;

          if (attribs.id === 'main') {
            return (
              <h1 style={{ fontSize: 42 }}>
                {domToReact(children)}
              </h1>
            );
          } else if (attribs.class === 'prettify') {
            return (
              <span style={{ color: 'hotpink' }}>
                {domToReact(children)}
              </span>
            );
          }
        }
      }
    )}
  </>

我没有传递parserOptions给该domToReact函数,因为我还没有找到这些选项的文档。

预期成绩:

<h1 style="font-size:42px">
  <span style="color:hotpink">keep me and make me pretty!</span>
</h1>

到目前为止,我无法修改嵌套节点(在本例中<span>)。

实际结果:

<h1 style="font-size: 42px;">
    <span class="prettify">keep me and make me pretty!</span>
  </h1>
4

2 回答 2

1

我有这个没有domToReact选择的工作。我将从从 Wordpress 获取的 JSON 对象传递一个 HTML 字符串到react-syntax-highlighter. 我还没有检查html-react-parser源代码以了解使用两者之间的区别,但是用 JSX 替换 HTML 标记似乎可以正常工作domNode.attribs

该组件采用 JSON 对象(由 Wordpress 帖子组成),将每个帖子映射到单独的已解析部分,然后将每个pre已解析部分中满足特定条件(在本例中为class=wp-block-codeclass=CodeMirror)的每个标签替换为 JSXSyntaxHighlighter标签,同时保留代码块的文本 ( domNode.children[0].data)。

注释:在分析 JSON 对象时,我发现这些domNode.children数组中没有一个位置超过一个,因此[0]在我的情况下,位置就是所需要的全部 - 显然,您的需求可能会有所不同。

来自 Wordpress的命令html-react-parser或从 Wordpress 检索到的 JSON 对象都没有被解构,因此您可以清楚地看到 API/命令的描述。

import parse from 'html-react-parser';
import SyntaxHighlighter from 'react-syntax-highlighter';
import { gruvboxDark } from 'react-syntax-highlighter/dist/esm/styles/hljs';

export const Blog = (props) => {
  return (
    <div>
      <h1>This is an example of a blog component</h1>
      <div>
        {props.posts.map((post, index) => (
          <div key={post.id}>
            <h3>{post.id}</h3>
            <div>{parse(post.title.rendered)}</div>
            <div>{parse(post.excerpt.rendered)}</div>
            <div>
              {parse(post.content.rendered, {
                replace: (domNode) => {
                  if (
                    (domNode.attribs && domNode.attribs.class === 'CodeMirror') ||
                    (domNode.attribs && domNode.attribs.class === 'wp-block-code')
                  ) {
                    return (
                      <SyntaxHighlighter
                        language="bash"
                        showLineNumbers={true}
                        style={gruvboxDark}
                        wrapLongLines={true}
                      >
                        {domNode.children[0].data}
                      </SyntaxHighlighter>
                    );
                  }
                },
              })}
            </div>
          </div>
        ))}
      </div>
    </div>
  );
};
于 2021-05-03T20:24:42.810 回答
0

您必须将replace函数domToReact作为其options参数的一部分传递给。从来源:

/**
 * Converts DOM nodes to React elements.
 *
 * @param  {Array}    nodes             - The DOM nodes.
 * @param  {Object}   [options]         - The additional options.
 * @param  {Function} [options.replace] - The replace method.
 * @return {ReactElement|Array}
 */

在这个例子的情况下,这意味着......

function replaceHtmlWithReact({ attribs, children }) {
  if (!attribs) return;

  if (attribs.id === 'main') {
    return (
      <h1 style={{ fontSize: 42 }}>
        {domToReact(children, { replace: replaceHtmlWithReact })}
      </h1>
    );
  } else if (attribs.class === 'prettify') {
    return (
      <span style={{ color: 'hotpink' }}>
        {domToReact(children, { replace: replaceHtmlWithReact })}
      </span>
    );
  }
}

const test = () => 
<>
  {parse(
    `
      <p id="main">
        <span class="prettify">
          keep me and make me pretty!
        </span>
      </p>
    `,{ replace: replaceHtmlWithReact }
  )}
</>
于 2019-04-03T19:26:05.160 回答