Raect 异步加载组件
首先需要知道的是 dynamic import 通过返回 Promise 的方式实现异步加载功能。
import('./component.js')
.then((m) => {
// 处理异步加载到的模块m
})
.catch((err) => {
// 错误处理
});
要注意的是 import 的参数不能使用变量,简单原则是至少要让 Webpack 知晓应该预先加载哪些内容。这里的参数除了使用常量之外,还可以使用模板字符串 componentDir/${name}.js
。
其实到这里基本完成代码切割了,接下来做得就是结合 react-router 实现按模块异步加载。这是跟业务代码相关的,因此每个人的做法都是不一样的。所以以下代码仅供参考。
异步加载
我参考 react-router 的例子写了个简单的异步加载组件 AsyncLoader.js,内容:
import React from 'react';
export default class AsyncLoader extends React.Component {
static propTypes = {
path: React.PropTypes.string.isRequired,
loading: React.PropTypes.element,
};
static defaultProps = {
path: '',
loading: <p>Loading...</p>,
error: <p>Error</p>
};
constructor(props) {
super(props);
this.state = {
module: null
};
}
componentWillMount() {
this.load(this.props);
}
componentWillReceiveProps(nextProps) {
if (nextProps.path !== this.props.path
|| nextProps.error !== this.props.error
|| nextProps.loading !== this.props.loading) {
this.load(nextProps);
}
}
load(props) {
this.setState({module: props.loading});
// TODO:异步代码的路径希望做成可以配置的方式
import(`./path/${props.path}`)
.then((m) => {
let Module = m.default ? m.default : m;
console.log("module: ", Module);
this.setState({module: <Module/>});
}).catch(() => {
this.setState({module: props.error});
});
}
render() {
return this.state.module;
}
}
使用方法
<Route
exact path='/book'
render={()=><AsyncLoader path={'./components/Book.js'}/>}
/>
Webpack 打包的时候会根据 import 的参数生成相应的 js 文件,默认使用 id(webpack 生成的,从 0 开始)命名这个文件。
const Search = asyncComponent(() => import(/* webpackChunkName: "search" */ "./containers/Search/SearchContainer"))
const BookList = asyncComponent(() => import(/* webpackChunkName: "bookList" */ "./containers/BookList/BookListContainer"))
import React from 'react'
export const asyncComponent = loadComponent => (
class AsyncComponent extends React.Component {
state = {
Component: null,
}
componentWillMount() {
if (this.hasLoadedComponent()) {
return;
}
loadComponent()
.then(module => module.default) ////兼容 module.default ? module.default : module
.then((Component) => {
this.setState({ Component });
})
.catch((err) => {
console.error(`Cannot load component in <AsyncComponent />`);
throw err;
});
}
hasLoadedComponent() {
return this.state.Component !== null;
}
render() {
const { Component } = this.state;
return (Component) ? <Component {...this.props} /> : null;
}
}
);
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
上一篇: Redux 学习笔记
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论