@xiaoqq
2017-01-04T02:43:30.000000Z
字数 4704
阅读 1216
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;