@xiaoqq
2017-01-04T02:43:30.000000Z
字数 4704
阅读 1269
Webpack
import LazilyLoadFactory, { CreateLazilyModule } from '../../utils/LazilyLoad'
(1)
LazilyLoadFactory(Component, modulesName):
可以使用LazilyLoadFactory来代替每个页面的import方法,实现每个页面依赖项的懒加载。
modulesName可以为字符串或字符串数组。
Demo:
class PageTest extends React.Component {render() {const { Breadcrumb, Table, Pagination } = this.props;return (<div id="page-test"><Breadcrumb menuDataList={this.props.menuDataList} />...</div>)}}PageTest = LazilyLoadFactory(PageTest, ["Breadcrumb", "CTable", "Pagination"])
(2)
CreateLazilyModule(modulesName, moduleFn):
moduleFn为render函数,并且依赖于一个或多个模块(modulesName)。
比如:moduleFn中包含一个弹窗,弹窗中的组件并不希望其马上被加载,而是在弹窗显示的时候才会去异步加载。
modulesName可以为字符串或字符串数组。
Demo:
renderDatePicker = ({DatePicker}) => {return <DatePicker type="datetime" placeholder="请选择" onChange = {() => {Modal.alert(this.state.currentPage)}}/>}renderModuleEdit() {return (<div className="padding-20" id="edit-module">//renderDatePicker函数依赖的DatePicker,必须要在CreateLazilyModule中声明,{CreateLazilyModule("DatePicker", this.renderDatePicker)}</div>)}
如果要从renderModuleEdit函数向renderDatePicker传递参数,可以通过bind函数
renderDatePicker(test, {DatePicker}) {return <DatePicker type="datetime" placeholder="请选择" onChange = {() => {Modal.alert(test + this.state.currentPage);}}/>}renderModuleEdit() {let test = "当前的页面是:";return (<div className="padding-20" id="edit-module">//我们可以使用bind函数给renderDatePicker绑定test参数{CreateLazilyModule("DatePicker", this.renderDatePicker.bind(this, test))}</div>)
源码:
import React from 'react';/*** @function 支持异步加载的封装组件*/export class LazilyLoad extends React.Component {constructor() {super(...arguments);this.state = {isLoaded: false,};}componentWillMount() {this.load(this.props);}componentDidMount() {this._isMounted = true;}componentWillReceiveProps(next) {if (next.modules === this.props.modules) return null;this.load(next);}componentWillUnmount() {this._isMounted = false;}load(props) {this.setState({isLoaded: false,});const {modules} = props;const keys = Object.keys(modules);Promise.all(keys.map((key) => modules[key]())).then((values) => (keys.reduce((agg, key, index) => {agg[key] = values[index];return agg;}, {}))).then((result) => {if (!this._isMounted) return null;this.setState({modules: result, isLoaded: true});});}render() {if (!this.state.isLoaded) return null;return React.Children.only(this.props.children(this.state.modules));}}LazilyLoad.propTypes = {children: React.PropTypes.func.isRequired,};/*** 声明所有的组件及路径,这个对象需要不断更新* @type {Object}*/const ComponentMap = {BaseTable: () => System.import('../components/basetable'),Breadcrumb: () => System.import('../components/breadcrumb'),CTable: () => System.import('../components/cTable'),DatePicker: () => System.import('../components/datepicker'),Dropdown: () => System.import('../components/dropdown'),Overlay: () => System.import('../components/overlay'),Pagination: () => System.import('../components/pagination'),InputSelect: () => System.import('../components/select/inputSelect'),NormalSelect: () => System.import('../components/select/normalSelect'),RealtimeSelect: () => System.import('../components/select/realtimeSelect'),}/*** 使用场景:组件Component依赖于一个或多个模块(modulesName),而且这些模块需要被异步加载* 比如:我们可以使用LazilyLoadFactory来代替每个页面的`import`方法,实现每个页面依赖项的懒加载* LazilyLoadFactory返回的是一个新的组件(本质上是一个函数)* @param {[type]} Component [description]* @param {[String Or Array]} modulesName [Component所需要异步加载的模块,modulesName的类型必须为字符串或字符串数组]* @return {[Component]} [description]*/const LazilyLoadFactory = (Component, modulesName) => {let modules = {};if(modulesName instanceof Array) {modulesName.forEach(list => {if(!ComponentMap[list]) {console.error(`${list}组件未找到,请检查拼写。`);}modules = {...modules, [list]: ComponentMap[list]}});}else if(typeof(modulesName) == 'string') {if(!ComponentMap[modulesName]) {console.error(`${modulesName}组件未找到,请检查拼写。`);}modules[modulesName] = ComponentMap[modulesName]}else {console.error("ModulesName 必须为字符串或字符串数组。");return;}return (props) => (<LazilyLoad modules={modules}>{(mods) => <Component {...mods} {...props} />}</LazilyLoad>);};/*** 使用场景:moduleFn为一个render函数,并且依赖于一个或多个模块(modulesName)* 比如:moduleFn中包含一个弹窗,弹窗中的组件并不希望其马上被加载,而是在弹窗显示的时候才会去异步加载* CreateLazilyModule返回的是一个对象* @param {[type]} modulesName [description]* @param {[type]} moduleFn [Component所需要异步加载的模块,modulesName的类型必须为字符串或字符串数组]* @return {[Object]} [description]*/export const CreateLazilyModule = (modulesName, moduleFn) => {let modules = {};if(modulesName instanceof Array) {modulesName.forEach(list => {if(!ComponentMap[list]) {console.error(`${list}组件未找到,请检查拼写。`);}modules = {...modules, [list]: ComponentMap[list]}});}else if(typeof(modulesName) == 'string') {if(!ComponentMap[modulesName]) {console.error(`${modulesName}组件未找到,请检查拼写。`);}modules[modulesName] = ComponentMap[modulesName]}else {console.error("ModulesName 必须为字符串或字符串数组。");return;}return (<LazilyLoad modules={modules}>{moduleFn}</LazilyLoad>)};export const importLazy = (promise) => (promise.then((result) => result));export default LazilyLoadFactory;