React 異步組件

React 經過react-loadable實現異步組件

在通常的react項目中在性能優化方面除了減小各類靜態資源的體積外,還有一個效果顯著的方式,異步加載組件,包括頁面級組件(在路由中配置的),以及其餘的體積較大的第三方組件(bizcharts,bScroll,...),本文會詳細說明使用react-loaable來實現三種異步組件:javascript

  1. 頁面級組件(router.js引用的組件),普通的react組件
  2. bizcharts 組合的react組件
  3. bScroll 等非典型react組件(第三方類庫)

準備

項目中安裝 react-loadble ,babel插件安裝 syntax-dynamic-import. react-loadable是經過webpack的異步import實現的 若是要實現非頁面的組件加載,首先要在webpack配置中將相應的代碼塊分離出來,splitchunk!!! (例如,bizcharts 等代碼庫,須要在splitchunk中給個單獨配置)java

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

如今咱們來說list頁面實現異步組件,其中在Loadable方法的參數配置中,react

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}webpack

頁面級組件(router.js引用的組件),普通的react組件

未使用react-loadable以前的頁面,以下:web

// 首次加載
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 文件bash

export A =()=>{<div>A</div>};
export B =()=>{<div>B</div>};
export C =()=>{<div>C</div>};
複製代碼

此時要加載A頁面,須要在render函數中的loaded參數得到A屬性即A組件babel

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組件。ide

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 若是是一個集合,能夠直接出入,在使用的組件中獲取

相關文章
相關標籤/搜索