【问题标题】:How can i render a React JS component directly & without a Target container如何在没有 Target 容器的情况下直接渲染 React JS 组件
【发布时间】:2019-08-02 11:17:51
【问题描述】:

我想在没有 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;
  }
}

【问题讨论】:

  • 你期望它会在哪里渲染?!
  • 就在你插入生成的JS文件的地方,就像这个例子github.com/seriousben/embeddable-react-widget
  • @Elchy 即使是您发送的链接,也有一个呈现小部件的 HTML。
  • 任何要呈现的 HTML 元素都需要一个容器。然而,这个容器可以在运行时由 JS 在文档加载时生成。
  • @minus.273 是的,但它不是手动插入的!你只有

标签: javascript reactjs frontend


【解决方案1】:

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

更新:

虽然感觉很奇怪,但实际上你可以在调用 ReactDOM.render 之前 获取你的 bundle 的脚本标签。

知道了这一点,你可以这样做:

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

尽管上面的 sn-p 应该按预期工作(我的测试通过了),但我不确定在生产中使用它是否安全。

【讨论】:

    猜你喜欢
    • 2020-08-18
    • 2023-02-22
    • 2022-01-19
    • 2020-08-31
    • 1970-01-01
    • 2021-10-28
    • 2016-09-27
    • 1970-01-01
    • 2017-09-19
    相关资源
    最近更新 更多