React 异步组件

作者: pipu | 来源:发表于2019-03-23 11:33 被阅读174次

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
如果是一个集合,可以直接出入,在使用的组件中获取

相关文章

  • react记录 二

    目录 一.react异步加载组件,分模块加载,提高打开性能 二. 三. 四. 一.react异步加载组件,分模块加...

  • React 异步组件

    React 通过react-loadable实现异步组件 在一般的react项目中在性能优化方面除了减少各种静态资...

  • react异步组件

    正常情况下,我们进入项目,在各个页面跳转,这个时候,在控制台可以看到,只加载了bundle.js文件。也就是说,我...

  • Recoil学习(三)---异步、同步

    Recoil通过数据流图将数据及衍生数据映射给组件,其真正强大之处是可异步,我们可以react组件中使用异步函数。...

  • react异步加载组件

    ☼ 注:笔者的文章是根据自己当前项目做的笔记,具体应用请参照自己实际项目情况 1、在根目录新建一个asyncLoa...

  • react异步加载组件

    实用方法

  • react 异步加载组件

  • react异步加载组件与代码分割

    继续学习github高赞项目react-pxq 项目router中引入了路由组件,使用了异步加载的模式 异步加载组...

  • this.setState是同步还是异步

    1、在组件的生命周期或者React合成事件中,是异步 2、在setTimeout或者原生dom事件中,是同步 异步...

  • react-router4.x 按需加载的实现方式

    第一种 create-react-app文档给的react-router按需加载实现: 创建一个异步组件 As...

网友评论

    本文标题:React 异步组件

    本文链接:https://www.haomeiwen.com/subject/siojvqtx.html