2016-11-09 218 views
1

所以情况 - 我想创建应用程序\框架,它将利用React和用户\第三方构建组件(Widgets)。我目前的观点是,我将有一个根组件,它将列出加载的第三方组件。像这样:将(外部)组件动态加载到React.js

class Root { 
constructor(p){ 
    this.state = {loadedWidgets: [<Chat/>, <Mail/>, <Notes/>]} 
} 
render(){ 
    return(
    <div> 
    <Header/> 
    <Body> 
    {this.state.loadedWidgets.map(WidgetName => <WidgetName />)} 
    </Body> 
    </div> 
) 
} 
} 

但我遇到我无法理解或找到如何解决两大问题:

  1. 我将如何加载(进口)的部件不是,如果我要硬代码他们到根组件? (我想我可以做一些钩子,这样以后用户安装,它会被添加到状态,不知何故窗口小部件)
  2. 为什么阵营不会呈现真正的组件方式:

(代码列表结束标记正常工作)

render(){ 
    const NameOfACustomComponent = this.state.loadedWidgets[0] 
    return(<div><NameOfACustomComponent/></div> 
} 

渲染后它将是一个自定义DOM标记,而不是现有的React组件。

我想要构建的是Chrome为用户经常使用的小部件\应用替换新页面的扩展,同时为开发人员提供了使用纯React.js以足够简单的方式添加新小部件的可能性和一些整合的钩子。

编辑。根据this issue找到第二个问题的答案如果您有对其类或函数的引用(ES5 React样式),则React允许创建任意组件。因此,对于2和1问题的解决方案之一是在窗口对象中有一些注册表,其中任何组件都可以将其自身添加并提供给框架。虽然它应该以严格的Class实例方式完成,以提供一种方法来添加\只删除Widget本身,而不是它们的完整列表。

+0

第三方组件是由React? –

回答

1

就快,改变

{this.state.loadedWidgets.map(WidgetName => <WidgetName />)} 

{this.state.loadedWidgets.map(Widget => Widget)} 

或很可能也应该工作:

{this.state.loadedWidgets} 
+0

是的,在阅读编辑中提到的问题之后,我明白我将不得不引用所有组件,但首先我想到了一些神奇的方式让React通过他们的名字了解其所有组件。现在我明白,它只能操作知道它应该使用的组件。 –

0

对不起,我无法发布全面的解决方案早。

动态组件加载的主要问题首先是警告主渲染器组件添加或删除一些DC(动态组件)的方式。第二个是较小的,可以很容易地通过解决第一个通过处理组件操作的对象来解决,因此任何DC都可以自己添加,而这个对象(RDCL)会提醒任何订阅者。 样品RDCL可能看起来像:

class RDCL extends Array { //so we could use filtering and stuff 
    subscribe(componentType, callback) { // handle the way to notify subscriber when C. with corerct type added to RDCL } 
    unsubscribe(componentType = ALL, callback) { // remove subscription } 
    add(componentClassOrFunctionDefinition, [typeGoesHere?]) { // add component with default or provided or included type } 
    remove(componentClassOrFunctionDefinition) { // remove component } 
} 

虽然与动态第三方组件出现另一个问题 - 如何处理,而不包括捆绑反应,并且已经包含在主应用程序\框架的所有库。对于这一个,我仍然没有答案,除了在其中使用类型/ babel的纯脚本

如果您不需要第三方组件,但想要在应用程序中的任何位置动态加载它们, (也许很肮脏)解决方案:

window.ReactComponentRegistry = {}; // somewhere in root component 

// some component that should be loaded dynamicaly (somewhat) 
class SomeComponent exteds Component { // ... }; 
window.ReactComponentRegistry['SomeComponentName'] = SomeComponent; 

//render() of view that would use that dynamic component 
const ArbitraryComponent = window.ReactComponentRegistry.SomeComponentName // ['SomeComponentName'] obviously will work too 
return(<ArbitraryComponent props={this.props} />);