之前讲过,webpack4.0的optimization 下面的splitchunkplugin可以分割异步组件,从而减少过度的首页渲染问题。那么如何写一个异步组件呢?可以从下面几种方法入手:
1、借助es6的import().then,手写一个异步高阶组件
import React from 'react';
export default (getComponent) => {
return class AsyncComponent extends React.Component {
static Component = null;
state = { Component: AsyncComponent.Component };
componentWillMount() {
if(!this.Component) {
let rs = getComponent();
rs.then(({default: Component}) => {
AsyncComponent.Component = Component;
this.setState({ Component })
})
}
}
render() {
const { Component } = this.state;
if(Component) {
return <Component {...this.props} />
}
return null
}
}
}
;
页面中的使用方法如下:
import React, { useState } from 'react';
import Navigator from '../../layout/navigator/index.jsx';
import AsyncComponent from '../../utils/AsyncComponent.js';
import './index.css';
const mapCom = {
tab1: () => import('./components/tab1.jsx'),
tab2: () => import('./components/tab2.jsx'),
tab3: () => import('./components/tab3.jsx')
}
const Home = function(props) {
const [tab, setTab] = useState('tab1');
let TabContent = AsyncComponent(mapCom[tab]);
return (
<div>
<div
style={{
display: 'flex'
}}
onClick={e => {
setTab(e.target.className);
}}
>
<div className={tab === "tab1" ? "tab1 active" : "tab1"}>
tab1
</div>
<div className={tab === "tab2" ? "tab2 active" : "tab2"}>
tab2
</div>
<div className={tab === "tab3" ? "tab3 active" : "tab3"}>
tab3
</div>
</div>
<div>
{
<TabContent />
}
</div>
</div>
)
}
export default Navigator(Home);
路由里的使用方法如下:
import { UploadOutlined, UserOutlined, VideoCameraOutlined } from '@ant-design/icons';
import AsyncComponent from '../utils/AsyncComponent.js';
const Root = import('../view/root/index.jsx')
const Login = import('../view/login/index.jsx');
const Home = import('../view/home/index.jsx');
const routes = [
{
icon: UploadOutlined,
name: 'root',
path: '/',
component: AsyncComponent(() => Root),
},
{
icon: UserOutlined,
name: 'login',
path: '/login',
component: AsyncComponent(() => Login),
},
{
icon: VideoCameraOutlined,
name: 'home',
path: '/home',
component: AsyncComponent(() => Home),
}
];
export default routes
2、使用React 中的suspend lazy模式
import React, { useState, lazy, Suspense } from 'react';
import Navigator from '../../layout/navigator/index.jsx';
import './index.css';
const mapCom = {
tab1: () => import('./components/tab1.jsx'),
tab2: () => import('./components/tab2.jsx'),
tab3: () => import('./components/tab3.jsx')
}
const Home = function(props) {
const [tab, setTab] = useState('tab1');
let TabContent = lazy(mapCom[tab]);
return (
<Suspense fallback={<div>Loading...</div>}>
<div>
<h1>
这里我使用的是React lazy 模式下的异步加载
</h1>
<div
style={{
display: 'flex'
}}
onClick={e => {
setTab(e.target.className);
}}
>
<div className={tab === "tab1" ? "tab1 active" : "tab1"}>
tab1
</div>
<div className={tab === "tab2" ? "tab2 active" : "tab2"}>
tab2
</div>
<div className={tab === "tab3" ? "tab3 active" : "tab3"}>
tab3
</div>
</div>
<div>
{
<TabContent />
}
</div>
</div>
</Suspense>
)
}
export default Navigator(Home);
suspense还有很多其他的用法,可以处理多个异步请求数据之后再渲染组件的情况
看下在dist下面都生成了什么
很神奇,都是一个分割后的代码,打开其中一个看下,发现是利用了jsonp来加载这些分离的异步组件的
看下页面的效果吧
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。