从普通 JavaScript 添加 React 组件

Add React components from plain JavaScript

背景

我没有多少 React 经验。我正在使用 React 和 Redux 编写一个可嵌入的小部件。此小部件可以多次包含在同一网页上,每次都有自己的设置。

问题

我只想包含一次 React 应用 JS。因此,如果小部件在单个页面上被多次包含,它会在第一次加载应用程序 JS,然后对于每个后续包含,它会检查 JS 是否已经包含,如果是,则不会再次包含。

到目前为止,我只能初始化第一个小部件实例,这发生在加载 React 应用程序 JS 时。我在想我想为每个后续小部件进行轻量级(vanilla JavaScript)调用,以将具有该小部件设置的 React 组件渲染到 DOM.

我似乎无法弄清楚如何进行简单的 JavaScript 调用以使 React 呈现新组件。

长什么样子

<script type="text/javascript" src="http://example.com/widget/1"></script>
<script type="text/javascript" src="http://example.com/widget/2"></script>

第一个脚本标签将脚本标签添加到包含主要 React 应用程序 JS 的页面。这是一个大文件,~800 KB。它包含所有 React/Redux 库内容和我的 React 组件定义。它呈现一个 React 组件并将 ID 1 传递给它。

第二个脚本标签真的不应该为了在页面上创建新组件而再次包含该文件。我只希望它在 DOM 中呈现一个新的 React 组件并将 ID 2.

传递给它

要渲染 React 元素,只需调用:

ReactDOM.render(react_element, dom_element);

其中 dom_element 是您希望反应元素在页面中出现的位置。 Relevant docs.

如果你想防止多重包含 JavaScript,只需编写你的脚本,使其首先检查它是否已经 运行,如果有则立即退出。

当然,您的小部件还需要加载 React 脚本并等待它们准备就绪后再继续。你可以这样做:

if (!window.MyWidgetPromise) {
  window.MyWidgetPromise = script([
    'https://unpkg.com/react@15/dist/react.js',
    'https://unpkg.com/react-dom@15/dist/react-dom.js'       
  ]).then(function() {
    return React.createClass(...);
  })
}
window.MyWidgetPromise.then(function(widget) {
  ReactDOM.render(widget, TARGET_ELEMENT);
})

假设您正在使用 this promise-based script loader

或者,您可以让这个小部件的第一个包含呈现页面中需要的小部件的所有实例,然后让后续包含不执行任何操作,如下所示:

if (!window.MyWidgetPromise) {
  window.MyWidgetPromise = script([
    'https://unpkg.com/react@15/dist/react.js',
    'https://unpkg.com/react-dom@15/dist/react-dom.js'       
  }).then(function() {
    var widget = React.createClass(...);
    document.querySelector('my-widget').forEach(function(element) {
      ReactDOM.render(widget, element);
    })
  })
}

不过,如果将其包装在文档就绪处理程序中效果会更好,因此您可以确保所有受影响的元素都将存在于 querySelector 运行 之前的 DOM 中。