React.js:是否可以将 React 组件转换为 HTML DOM?

问题描述 投票:0回答:7

我正在开发一个基于地图的应用程序,该应用程序使用 Google Map API 在 React.js 中创建标记及其信息窗口。

infowindow.setContent()
只接受
String
HTML
。我不可能传入
String
,因为我有一个
button
链接到另一个反应组件中的特定方法(类似于:
_this.props.addList(place)
)。因此,我必须将参数填充为 HTML DOM,如下代码行:

var div = document.createElement('div');
var title = document.createElement('h4');
title.innerHTML = place.name;

var btn = document.createElement('button');
btn.className = 'btn btn-danger btn-block';
btn.appendChild(document.createTextNode('I want to go here !!'));

div.appendChild(title).appendChild(btn);

google.maps.event.addListener(marker, 'click', function() {

  infowindow.setContent( div );
  infowindow.open(map, this);
});

btn.addEventListener('click', function() {
  _this.props.addList(place);
});

这些代码对我有用,但我不想一个一个地创建元素。我也尝试过使用 React 组件传递参数,但它似乎不起作用:

createMarker: function() {
  
  /** Some other lines of code */

  var _this = this;

  google.maps.event.addListener(marker, 'click', function() {

    infowindow.setContent( _this._renderInfoWindow(place) );
    infowindow.open(map, _this);

  });

},

// my infowindow rendering method
_renderInfoWindow: function(place) {
  return(
    <div>
      <h4>{place.name}</h4>
      <p>{place.cost}</p>
      <button className="btn btn-danger btn-block" onClick={this.props.addList.bind(this, place)}>I want to go here !! </button>
    </div>
  )
},

那么有没有另一种方法至少将 React 组件转换为 HTML,这样我就不必一个接一个地编写

document.createElement()

谢谢

javascript reactjs
7个回答
24
投票

您可以通过

React.render
在分离的 DOM 节点中呈现 ReactElement。因此,以下代码应该适合您。

createMarker: function() {

  /** Some other lines of code */

  _this = this;

  google.maps.event.addListener(marker, 'click', function() {

    var div = document.createElement('div');
    ReactDOM.render( _this._renderInfoWindow(place), div );
    infowindow.setContent( div );
    infowindow.open(map, this);

  });

},

17
投票

你也可以使用 React 的 renderToString() 方法

_renderInfoWindow: function(place) {
  return React.renderToString(
    <div>
      <h4>{place.name}</h4>
      <p>{place.cost}</p>
      <button className="btn btn-danger btn-block" onClick={this.props.addList.bind(this, place)}>I want to go here !! </button>
    </div>
  );
}

这应该适用于如图所示的简单组件。 React.renderToString() 将只返回组件的 html。


14
投票

对于较新版本的 React

import ReactDOMServer from "react-dom/server";

let html = ReactDOMServer.renderToString(<div>...</div>)

3
投票

这应该呈现 HTML。

import ReactDOMServer from "react-dom/server";

const html = ReactDOMServer.renderToString(<div>...</div>)

1
投票

Alexandre 的方法现在已被弃用,而且从来都不是惯用的。这是新的方式,写得地道:

createMarker: function() {

  /** Some other lines of code */

  _this = this;

  google.maps.event.addListener(marker, 'click', function() {

    var div = document.createElement('div');
    const root = ReactDOM.createRoot(div)
    root.render(<InfoWindow place={place} addList={...} />));
    infowindow.setContent(div);
    infowindow.open(map, this);

  });

},

// my infowindow rendering method
function InfoWindow ({ place, addList }) {
  return(
    <div>
      <h4>{place.name}</h4>
      <p>{place.cost}</p>
      <button className="btn btn-danger btn-block" onClick={() => addList(place)}>I want to go here !! </button>
    </div>
  )
},

注意将 JSX 混合到点击处理程序中,并将 InfoWindow 提取到它自己的组件中:惯用的 React。

下一个要解决的问题是在同一节点上创建多个根。这可以通过保存在一个共享的文件中来解决:

constructor() {
  this.infoWindowDiv = document.createElement('div');
  this.infoWindowReactRoot = ReactDOM.createRoot(this.infoWindowDiv)
}

后来……

this.infoWindowReactRoot.render(<InfoWindow place={place} addList={...} />));

0
投票
// Create a DOM element to hold the react component.
var span = document.createElement('span');
// Render the React component.
React.render(h.button(null, 'Buttonz!'), span);
// This will give the result as a string, which is useful if you've escaped
// React's context (e.g. inside DataTables).
// Obviously, the component will no longer be reactive but this is a
// good way to leverage simple stuff you've already written in React.
// In my case, I'm primarily leveraging React wrappers around Bootstrap components.
// The important thing is that componentDidMount gets called.
return span.outerHTML;

0
投票

这就是 React 18 中应该如何完成的:

import { createRoot } from 'react-dom/client';
import { flushSync } from 'react-dom';

const div = document.createElement('div');
const root = createRoot(div);
flushSync(() => {
  root.render(<MyIcon />);
});
console.log(div.innerHTML); // For example, "<svg>...</svg>"

我在尝试迁移到 React 18 时缺少的主要部分是

flushSync
部分。在添加之前我的
innerHtml
总是返回空字符串。

根据这篇文章:https://react.dev/reference/react-dom/server/renderToString#removing-rendertostring-from-the-client-code

flushSync 调用是必要的,以便 DOM 在之前更新 读取它的 innerHTML 属性。

此外,

renderToString
和导入
react-dom/server
到浏览器仍然不推荐。

© www.soinside.com 2019 - 2024. All rights reserved.