【问题标题】:Unable to modify children in parsed html无法在已解析的 html 中修改子项
【发布时间】:2019-04-03 02:30:14
【问题描述】:

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

我测试了许多库,包括 html-react-parser。与许多其他人不同,html-react-parser 有一个满足我需求的示例。但是,我无法让这个例子起作用。 (使用 React 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>

到目前为止,我无法修改嵌套节点(在本例中为 &lt;span&gt;)。

实际结果:

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

【问题讨论】:

    标签: reactjs html-react-parser


    【解决方案1】:

    我在没有domToReact 选项的情况下工作。我正在将从 Wordpress 获取的 JSON 对象中的 HTML 字符串传递给react-syntax-highlighter。我还没有检查html-react-parser 源代码,看看使用两者之间有什么区别,但是用 JSX 替换 HTML 标记似乎可以与 domNode.attribs 一起工作。

    该组件获取 JSON 对象(由 Wordpress 帖子组成),将每个帖子映射到单独的已解析部分,然后替换每个已解析部分的每个 pre 标记满足特定条件(在本例中为 @ 987654326@ 或 class=CodeMirror) 带有 JSX SyntaxHighlighter 标签,同时保留代码块的文本 (domNode.children[0].data)。

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

    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>
      );
    };
    

    【讨论】:

      【解决方案2】:

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

      /**
       * 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 }
        )}
      </>
      

      【讨论】:

        猜你喜欢
        • 2013-01-28
        • 1970-01-01
        • 2018-09-10
        • 1970-01-01
        • 1970-01-01
        • 2022-12-18
        • 1970-01-01
        • 2011-01-31
        • 2011-10-09
        相关资源
        最近更新 更多