reactjs React.js:有可能将react组件转换成HTMLDOM吗?

a8jjtwal  于 2023-04-29  发布在  React
关注(0)|答案(7)|浏览(233)

我正在开发一个基于Map的应用程序,它使用Google Map API在React中创建标记和信息窗口。js。infowindow.setContent()只接受StringHTML。我不可能传入String,因为我有一个button链接到另一个react组件中的特定方法(类似于:_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()了?
谢谢

a2mppw5e

a2mppw5e1#

您可以通过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);

  });

},
3gtaxfhh

3gtaxfhh2#

你也可以使用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。

yzckvree

yzckvree3#

对于较新版本的React

import ReactDOMServer from "react-dom/server";

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

xzlaal3s4#

这应该会呈现HTML。

import ReactDOMServer from "react-dom/server";

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

lskq00tm5#

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混合到了click处理程序中,InfoWindow提取到了它自己的组件中:惯用React
下一个要解决的问题是在同一个节点上创建多个根。这可以通过保持在一个单一的,共享的一个来解决:

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

然后

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

8xiog9wr6#

// 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;
kqlmhetl

kqlmhetl7#

这就是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总是返回空字符串。
根据这篇文章: www.example.com
flushSync调用是必要的,这样DOM就可以在阅读其innerHTML属性之前更新。
此外,仍然不建议将renderToString和将react-dom/server导入浏览器。

相关问题