在后台从 React 组件制作 HTML 字符串,如何在另一个 React 组件中通过危险的SetInnerHTML 使用该字符串

Posted

技术标签:

【中文标题】在后台从 React 组件制作 HTML 字符串,如何在另一个 React 组件中通过危险的SetInnerHTML 使用该字符串【英文标题】:Making an HTML string from a React component in background, how to use the string by dangerouslySetInnerHTML in another React component 【发布时间】:2017-09-19 21:49:46 【问题描述】:

我正在尝试在 React 项目中渲染 LaTeX 字符串。 虽然我使用react-mathjax React 组件,但我想获得一个由 LaTeX 字符串组成的 html 字符串,以便将它和其他字符串连接起来,并通过 dangerouslySetInnerHTML 设置它。

我尝试过的当前代码

示例代码在这里:https://github.com/Nyoho/test-react-project/blob/component2string/src/components/tex.jsx

    LaTeX 字符串以字符串形式给出 document.createElement('span') 创建一个空的 DOM aDom(在后台。不在文档 DOM 树中。) 将ReactDOM.render的LaTeX字符串渲染成aDom 渲染后通过aDom.innerHTML.outerHTML获取字符串

问题

aDom.innerHTML(或.outerHTML)的值为"<span><span data-reactroot=\"\"></span></span>"(几乎为空) 尽管aDom 有一个由 MathJax 生成的完美树。

简单地说,

    aDom: ???? aDom.outerHTML: ????

A screenshot console.log of aDom and aDom.outerHTML

问题

如何从上面的aDom 获取“正确”的 HTML 字符串?

【问题讨论】:

【参考方案1】:

据我所知,你得到了你期望得到的。

给定一个根元素(在您的情况下为aDom),ReactDOM 将在该元素内呈现它的根组件,并且该组件的元素将具有data-reactroot 属性。

所以你所看到的正是它应该的样子。根据我的测试,内部 dom 树也应该在那里。

var Another = React.createClass(
  render: function() 
    return (
      <div>Just to see if other components are rendered as well</div>
    );
  
);

var Hello = React.createClass(
  render: function() 
    return (
      <div id="first"> 
        <div id="sec-1">Hello</div>
        <div id="sec-2"> this.props.name </div>
        <Another />
      </div>
    );
  
);

var a = document.createElement('div');

ReactDOM.render(
  <Hello name = "World" /> ,
  a
);

console.log(a.outerHTML);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>

控制台中的结果是:

<div><div data-reactroot="" id="first"><div id="sec-1">Hello</div><div id="sec-2">World</div><div>Just to see if other components are rendered as well</div></div></div>

【讨论】:

哎呀,我得到了我期望得到的东西!那么,问题可能是react-mathjax console.log(c)componentToString 函数的开头会得到什么? console.log(c)插入componentToString函数的第1行,我得到了imgur.com/6Q9sjNm(它似乎是一个React元素。) 我从您在问题中发布的屏幕截图中看到,MathJax 在 DOM 中插入了一个脚本标签,该标签可能会在相应的跨度中呈现输出。我相信这就是您在渲染到内存时发现跨度为空的原因。如果您确实需要这样做,您可以在真实 DOM (display: none) 中创建一个不可见的 div 并在此处渲染您的组件。您应该在那里获得完整的内容。 我想我只是不明白......你上面的示例代码和我的 MathJax 案例有什么区别?为什么你的案例不需要在页面的真实 DOM 中制作一个不可见的 div?【参考方案2】:

如果您想将任何组件呈现为 HTML 字符串,这似乎工作得很好:

import  renderToString  from 'react-dom/server'

renderToString() 
  return renderToString(<MyAwesomeComponent some="props" or="whatever" />)

【讨论】:

太棒了!谢谢! (抱歉来晚了。)我在 renderToString 分支中用renderToString 重写了它:github.com/NyohoSampleCodes/test-react-project/blob/… 但它似乎仍然是空的。 缺少function 吗?也许换个名字,重用导入的名字会让人困惑。 喜欢它!对于需要 html 字符串的属性来说太有用了。现在创建一个组件,然后将其字符串化为 html。美丽:)【参考方案3】:

我建议使用 renderToStaticMarkup 而不是 renderToString,因为它不会添加任何额外的 React 内部使用的 DOM 属性,例如 `data-reactroot:

import  renderToStaticMarkup  from 'react-dom/server'

getString() 
  return renderToStaticMarkup(<AnyComponent />)

文档:

【讨论】:

以上是关于在后台从 React 组件制作 HTML 字符串,如何在另一个 React 组件中通过危险的SetInnerHTML 使用该字符串的主要内容,如果未能解决你的问题,请参考以下文章

React后台管理系统-顶部NavTop组件设计

react服务端渲染(同构)

一步一步搭建react后台系统6之用户列表

在 React.js 中,我如何从组件的字符串表示中呈现组件?

E03:后台管理系统开发-登录界面UI制作

E03:后台管理系统开发-登录界面UI制作