React组件懒加载
Web应用一个重要的优势就在于可以只加载我们想要的功能,而不必每次打开都把整个系统载入
那么,在React里我们怎样实现当用到我们需求的功能时再请求对应的组件,而不是一次性的请求全部代码呢?
bundle-loader
新版的React建议我们使用bundle-loader进行代码的分离,下面我们看下它的用法:
// 当你用到这个函数时,这个chunk才会被请求
var waitForChunk = require("bundle-loader!./file.js");
// 当请求的chunk加载完成才会执行传入的回调函数,并将请求的模块作为参数传入回调函数
waitForChunk(function(file) {
// 接收到懒加载模块,类似于下面代码
// var file = require("./file.js");
});
这个插件使用非常简单,只是对require.ensure的封装,使用起来类似于AMD的方式,
只需在回调函数里接收到懒加载的模块即可。
结合React
React 组件也是模块,因此可以使用bundle-loader进行代码分离,只是需要在合适的地方请求调用即可。
怎样知道何时需要请求这个组件呢?社区建议的是先加载一个bundle容器组件(这个bundle容器组件本身非常小),当这个容器组件被渲染到dom时则可认为我们需要请求对应的懒加载组件了。
我们可以为所有的懒加载组件封装一个通用的容器组件:
(这里也有已经封装好的:react-lazy-bundle,直接安装即可)
import React, { Component } from "react";
class Bundle extends Component {
state = {
// 因为module被占用了,我们用mod定义变量
mod: null
};
componentWillMount() {
this.load(this.props);
}
componentWillReceiveProps(nextProps) {
if (nextProps.load !== this.props.load) {
this.load(nextProps);
}
}
load(props) {
this.setState({
mod: null
});
props.load(mod => {
this.setState({
// 为了兼容es module 和 AMD module
mod: mod.default ? mod.default : mod
});
});
}
render() {
//若加载完成则渲染对应懒加载的组件,反之加载beforeLoad传入的组件
return this.state.mod
? <this.state.mod {...this.props} />
: <this.props.beforeLoad {...this.props} />;
}
}
export default Bundle;
如上封装,使用时我们只需如下即可:
import React, { Component } from "react";
import Bundle from "./Bundle";
import Test from "bundle-loader?lazy&name=[name]!./test";
const BeforeLoadComponent = props =>
<div>
before load {props.name}
</div>;
class HomePage extends Component {
render() {
return (
<div>
<Bundle name="flypie" load={Test} beforeLoad={BeforeLoadComponent} />
</div>
);
}
}
export default HomePage;
怎么样,是不是特别简单
结合React Router
结合React Router也非常简单,因为已经把Bundle作为Route的component参数了,
所以要再封装一层,把load和beforeLoad预先传入即可。
import Bundle from "./Bundle";
import About from "bundle-loader?lazy&name=[name]!./About";
const AboutWrapper = props => <Bundle load={About} {...props}/>;
class App extends Component {
render() {
return (
<div>
<h1>Welcome!</h1>
<Route path="/about" component={AboutWrapper}/>
</div>
)
}
}
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。