如何在没有目标容器的情况下直接渲染React JS组件

时间:2019-08-02 11:17:51

标签: javascript reactjs frontend

我想直接在没有Target容器的情况下渲染组件,我需要在放置生成的JS文件的地方正确获取组件的内容。

这是我的index.js文件,我删除了“ document.getElementById('target-container')”,那里有一种方法可以在没有目标容器的情况下呈现此组件,或者可以在不插入目标容器的情况下追加目标容器在HTML模板文件中。

var React = require('react');
var ReactDOM = require('react-dom');
import axios from 'axios';
import '../node_modules/cleanslate/cleanslate.css';
import './style.scss';

class Widget extends React.Component {
constructor(props){
    super(props);
    this.state = {}
}

componentDidMount() {
    let id = this.props.id;
    axios.get(`https://api.com/${id}`)
    .then((res) => {
        const brand = res.data;
        this.setState({
            rating: brand.rating,
            logo : brand.logo,
            name: brand.name,
            stars: brand.stars,
            url: brand.url
        });
    });
}

render() {
    return (
        <div className="cleanslate">
            <a href={this.state.url} target="_blank">
                <img src="https://img/.svg" className="" alt="" />
                <div className="rating-box">
                    <img src={this.state.logo} className="logo" alt={this.state.name} />
                    <span className="note">{this.state.rating}/10</span>
                    <div id="Selector" className={`selected-${this.state.stars}`}></div>
                </div>
            </a>
        </div>
    )
}
}

ReactDOM.render(
    <Widget id="7182" />
)

以下是将组件附加到另一个示例中的示例(https://github.com/seriousben/embeddable-react-widget):

import React from 'react';
import ReactDOM from 'react-dom';
import Widget from '../components/widget';
import '../../vendor/cleanslate.css';

export default class EmbeddableWidget {
static el;

static mount({ parentElement = null, ...props } = {}) {
const component = <Widget {...props} />;

function doRender() {
  if (EmbeddableWidget.el) {
    throw new Error('EmbeddableWidget is already mounted, unmount first');
  }
  const el = document.createElement('div');
  el.setAttribute('class', 'cleanslate');

  if (parentElement) {
    document.querySelector(parentElement).appendChild(el);
  } else {
    document.body.appendChild(el);
  }
  ReactDOM.render(
    component,
    el,
  );
  EmbeddableWidget.el = el;
}
if (document.readyState === 'complete') {
  doRender();
} else {
  window.addEventListener('load', () => {
    doRender();
  });
}
  }

  static unmount() {
    if (!EmbeddableWidget.el) {
      throw new Error('EmbeddableWidget is not mounted, mount first');
    }
    ReactDOM.unmountComponentAtNode(EmbeddableWidget.el);
    EmbeddableWidget.el.parentNode.removeChild(EmbeddableWidget.el);
    EmbeddableWidget.el = null;
  }
}

1 个答案:

答案 0 :(得分:1)

您可以在调用ReactDOM.render(例如,如here中所述的appendChild)之前,使用JS为您的应用生成容器,然后调用ReactDOM,将刚刚生成的元素作为容器传递。

UPD:

即使感觉很奇怪,您实际上也可以在调用ReactDOM.render之前获得捆绑包的脚本标签。

知道这一点,您可以执行以下操作:

// Creates a container dynamically
let appContainer = document.createElement(`div`);

// Gets all <script>s on page and puts'em into an array.
let scriptTags = Array.from(document.getElementsByTagName(`script`));

// Filters scripts to find the one we need.
let targetScript = scriptTags.filter(
    scriptTag => scriptTag.src === `https://example.com/bundle.js` 
);

// Uh oh, we got either too many or too few,
// it might be bad, better stop right here.
if( targetScript.length !== 1 ) return;

// Inserts app container before the script.
document.body.insertBefore( appContainer, targetScript[0] );

// Renders things inside the container
ReactDOM.render (
    <MyComponent />,
    appContainer
);

即使上面的代码段可以按预期工作(我的测试通过了),但我不确定在生产环境中使用此代码是否安全。