React 异步组件

React 通过react-loadable实现异步组件

在一般的react项目中在性能优化方面除了减少各种静态资源的体积外,还有一个效果显著的方式,异步加载组件,包括页面级组件(在路由中配置的),以及其他的体积较大的第三方组件(bizcharts,bScroll,...),本文会详细说明使用react-loaable来实现三种异步组件:

  1. 页面级组件(router.js引用的组件),普通的react组件
  2. bizcharts 组合的react组件
  3. bScroll 等非典型react组件(第三方类库)
准备

项目中安装 react-loadble ,babel插件安装 syntax-dynamic-import. react-loadable是通过webpack的异步import实现的 如果要实现非页面的组件加载,首先要在webpack配置中将相应的代码块分离出来,splitchunk!!! (例如,bizcharts 等代码库,需要在splitchunk中给个单独配置)

react-loadable的基本使用和概念,其中import中的webpackChunkName是异步文件的文件名。

现在我们来讲list页面实现异步组件,其中在Loadable方法的参数配置中,


import Loadable from 'react-loadable';
// 首次加载
const Loading = ({ isLoading, error }) => {
    if (isLoading) {
        return <div>加载中...</div>;
    } else if (error) {
        return <div>页面加载出现问题, 请刷新后重试</div>;
    }
    return null;
};
const AsyncList = Loadable({
    loader: () => import(/* webpackChunkName: 'page_list' */'@pages/list'),
    loading: Loading
});

复制代码
  • loading 是一个接受状态对象的函数,isLoading和error属性,通过这两个属性来返回相应的过渡组件
  • loader 是一个返回import()调用的函数
  • render 如果loader中只是个普通的react组件这个办法不需要用到,但是如果加载的js或者组件时一个组件的集合就需要用到,其中loaded是加载的文件的export结果,props 是Loadable函数返回组件接收的参数。
    const A = Loadable({
        loader,
        render: (loaded, props) => {
            const CurComponent = 条件?loaded.default : loaded.other
            return <CurComponent {...props} />;
        },
        loading,
    });
    <A in={true} />
复制代码

此时props就是{in:tue}

页面级组件(router.js引用的组件),普通的react组件

未使用react-loadable之前的页面,如下:


// 首次加载
import Index from '@pages/index';
import List from '@pages/list';



const Routes = () => (
    <Router history={history}>
        <Route exact path="/index" component={Index} />
        <Route exact path="/list" component={List} />
    </Router>
);

复制代码

现在我们来讲list页面实现异步组件,其中在Loadable方法的参数配置中,可以根据项目需要修改loading中的过渡效果

import Loadable from 'react-loadable';
// 首次加载
import Index from '@pages/index';

const Loading = ({ isLoading, error }) => {
    if (isLoading) {
        return <div>加载中...</div>;
    } else if (error) {
        return <div>页面加载出现问题, 请刷新后重试</div>;
    }
    return null;
};
const AsyncList = Loadable({
    loader: () => import(/* webpackChunkName: 'page_list' */'@pages/list'),
    loading: Loading
});

const Routes = () => (
    <Router history={history}>
        <Route exact path="/index" component={Index} />
        <Route exact path="/list" component={AsyncList} />
    </Router>
复制代码

如果加载的js是个组件的集合,例如components.jsx 文件

export A =()=>{<div>A</div>};
export B =()=>{<div>B</div>};
export C =()=>{<div>C</div>};
复制代码

此时要加载A页面,需要在render函数中的loaded参数获得A属性即A组件

const AsyncA = Loadable({
    loader: () => import(/* webpackChunkName: 'page_list' */'@pages/list'),
    render: (loaded, props) => {
        const CurComponent = loaded.A; // A组件
        return <CurComponent {...props} />;
    },
    loading: Loading
});

复制代码

普通的react组件的加载类似普通的页面的加载

bizcharts 的异步实现,bizcharts的export类似上面的组件的组合,一般项目中用到的图表每个都会写到单独处理的文件里,chartA.js chartB.js,...,每个chart文件大概这样子:
import React from 'react';
import { Chart, Geom, Axis, Tooltip, Label, Guide, } from 'bizcharts';
class Index extends React.Component {
    render()
        return (
            <div>
                <Chart data={data} scale={scale} className="chart" forceFit >
                    <Axis name="score"  />
                    <Axis name="number"  />
                    <Tooltip triggerOn="none"/>
                    <Geom type="interval" position="score*number" ></Geom>
                </Chart>
            </div>
        );
    }
}

export default Index;
复制代码

先写一个通用的异步加载chart的函数getBizcharts,loading和上文提到的一样,函数的参数ReactComponent 就是原来的chartA,chartB组件 render 函数中的loader就是bizchart对象,通过getBizcharts函数就可以在chartA的组件的props.bizchart中获取和原来一样的bizcharts组件。

import Loadable from 'react-loadable';
export const getBizcharts = (ReactComponent) => Loadable({
    loader: () => import(/* webpackChunkName: "bizcharts" */'bizcharts'),
    render: (loaded, props) => <ReactComponent bizchart={loaded} {...props} />,
    loading: Loading
});

复制代码

这事图表组件的样子:

import React from 'react';
import { getBizcharts } from '@components/getAsyncComponent';
// import { Chart, Geom, Axis, Tooltip, Label, Guide, } from 'bizcharts';

class Index extends React.Component {
    render()
        const {
            Chart, Geom, Axis, Tooltip, Label, Guide,
        } = this.props.bizchart;
        return (
            <div>
                <Chart data={data} scale={scale} className="chart" forceFit >
                    <Axis name="score"  />
                    <Axis name="number"  />
                    <Tooltip triggerOn="none"/>
                    <Geom type="interval" position="score*number" ></Geom>
                </Chart>
            </div>
        );
    }
}

export default getBizcharts(Index);

复制代码

在render中通过props.bizchart获取bizchart组件,导出时调用getBizcharts方法

bScroll 等非react组件

如果该类组件的export 是一个单独的构造,就是在render的时候出入 loaded.default 如果是一个集合,可以直接出入,在使用的组件中获取

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值