2016-04-30 212 views
6

我需要动态加载反应组件。动态加载反应组件

我得到要从用户加载为字符串的组件名称。我正在使用webpack

如何动态加载组件,而不是使用静态导入语句。看来Require.Ensure不会评估表达式。我想要达到的是这样的。

require.ensure([ "./widgets/" + componentName ] ,(require) => { 
    let Component = require("./widgets/" + componentName); 
}); 

但这似乎并不奏效。

+0

'require.ensure'静态分析,正确。你会找到另一种方式。 –

+0

是否有可能使用webpack? – madCode

+0

你可以设置一个[require.context](https://webpack.github.io/docs/context.html)然后'require'。 –

回答

6

基本上,它归结为预先创建你将需要的所有块。那么你只需要一种方式来动态引用它们。这里的解决方案,我根据我的上:

http://henleyedition.com/implicit-code-splitting-with-react-router-and-webpack

这里是我做的,因为我不使用阵营路由器(边注:我不觉得这是对终极版或动画的良好匹配):

//loader: 
{ 
    test: (folder)\/.*\.js, 
    include: path.resolve(__dirname, 'src') 
    loader: ['lazy?bundle', 'babel'] 
} 

//dynamic usage within React component: 
const My_COMPONENTS = { 
    ComponentA: require('./folder/ComponentA'), 
    ComponentB: require('./folder/ComponentB'), 
} 

class ParentComponent extends React.Component { 
    componentDidMount() { 
     My_COMPONENTS[this.props.name](component => this.setState({component})); 
    } 
    render() { 
     return <this.state.component />; 
    } 
} 

所以结果是要动态渲染的成分,但是从静态组预定的可能性 - 所有一会儿,才不发送更多的客户比大块访问者实际感兴趣

另外,这里是一个组件我做这个好:

import React from 'react'; 
import Modal from './widgets/Modal'; 

export default class AjaxModal extends React.Component { 
    constructor(props, context) { 
    super(props, context); 
    this.state = { 
     Content: null 
    }; 
    } 

    componentDidMount() { 
    if(this.props.show) { 
     this.loadContent(); 
    } 
    } 

    componentWillReceiveProps({show}) { 
    if(show && !this.state.Content) { 
     this.loadContent(1200); //dont interfere with animation 
    } 
    } 

    loadContent(ms=0) { 
    setTimeout(() => { 
     this.props.requestLazyBundle(({default: Content}) => { 
     this.setState({Content}); 
     }); 
    }, ms); 
    } 

    render() { 
    let {Content} = this.state; 

    return (
     <Modal title={this.props.title} {...this.props} loading={!Content}> 
     {Content ? <Content /> : null} 
     </Modal> 
    ); 
    } 
} 

通通过异步需要捆绑功能this.props.requestLazybundle,就像这样:

render() { 

    let requestLazyBundle = require('bundle?lazy&name=AnotherComponent!../content/AnotherComponent'); 

    return (
    <AjaxModal title='Component Name' {...props} requestLazyBundle={requestLazyBundle} /> 
); 
} 
+0

如果你可以延迟加载webpack的文件,你可能也可以调整加载器来加载任何js文件? – Bill

+0

是的。你可以做动态需求,但是它们不能与SSR一起使用,例如https://github.com/faceyspacey/react-universal-component或React Loadable,直到webpack允许在其require.resolveWeak函数中进行动态需求。投票和评论我的问题在这里得到这个迟早:https://github.com/webpack/webpack/issues/4993 –

1

请看看,我已经提供了这个要点页面完整源代码 https://gist.github.com/SamanShafigh/a0fbc2483e75dc4d6f82ca534a6174d4

因此,假设您有4个组件,分别称为D1,D2,D3。你需要的是创建一个依赖注入和一个依赖容器机制。这是一个非常简单的实现

想象一下,你有这样的一个配置文件,它定义了组件

export default [ 
    { 
    name:'D1', 
    path:'D1' 
    }, 
    { 
    name:'D2', 
    path:'D2' 
    }, 
    { 
    name:'D3', 
    path:'D3' 
}]; 

然后你就可以有一个组件容器像这样

import componentsConfig from 'ComponentsConfig'; 

let components = {}; 

for (var i = 0; i < componentsConfig.length; i++) { 
    let componentConfig = componentsConfig[i]; 
    // Check if component is not already loaded then load it 
    if (components[componentConfig.name] === undefined) { 
    components[componentConfig.name] = require(`${componentConfig.path}`).default; 
    } 
} 

export default components; 

最后的地方你想加载你的组件,你可以使用你的组件容器来动态加载你的组件,或者换句话说,你可以注入你的组件

import React, { Component } from 'react'; 
import ComponentContainer from './ComponentContainer'; 

class App extends Component { 
    render() { 
    let components = ['D1', 'D2', 'D3']; 

    return (
     <div> 
     <h2>Dynamic Components Loading</h2> 
     {components.map((componentId) => { 
      let Component = ComponentContainer[componentId]; 
      return <Component>{componentId}</Component>; 
     })} 
     </div> 
    ); 
    } 
} 

export default App; 
+0

我试过相同的它不工作,错误:无法找到模块“。”。有没有工作回购?因为我尝试了所有可能的方式,但仍然一样。 –

+0

@LionelDcosta我已经提供了代码https://gist.github.com/SamanShafigh/a0fbc2483e75dc4d6f82ca534a6174d4但是请做更多的研究以找到这种方法的缺点,我不确定它是否适合大型项目 –