2016-04-30 192 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但是請做更多的研究以找到這種方法的缺點,我不確定它是否適合大型項目 –