美文网首页
按需加载

按需加载

作者: codingQi | 来源:发表于2019-06-03 19:09 被阅读0次

一、使用react-loadable

  1. 其中用到:loader: () => import('pages/home/index'),运行会报错:

  2. 经过提示进行安装:npm I -D @babel/plugin-syntax-dynamic-import,然后需要在babel里配置此plugin来支持,否则还是会报错。

plugins: [
    // 支持 () => import('./Home')语法
    '@babel/plugin-syntax-dynamic-import',
]
  1. 再次运行,成功。
  2. 页面使用如下:
    Loading组件的props有以下属性:
const Loading = (props) => {
    // props为下面的值
}
Loading组件的props
import Loadable from 'react-loadable';

// 加载中过渡组件
const Loading = ({ pastDelay }) => {
    if (pastDelay) { // 超过200ms则为true,没超过就为false
        return <p>loading</p>; // 当页面请求超过200ms就会显示loading,让用户等待。
    }
    return null; // 当页面请求很快时,不超过200ms,则页面直接加载组件,即空白页面。
};
// 动态引入Home组件
const Home = Loadable({
    loader: () => import('pages/home/index'),
    loading: Loading,
    delay: 200
});
const App = () => (
    <Router history={historyInstance}>
        <Switch>
            <Route exact path='/' component={Home} />
        </Switch>
    </Router>
);

二、使用React.Suspense(使用 React 的核心库,替换第三方库)

  1. app.js代码初步实现
import React, { Suspense } from 'react'; // 将lazy直接写在{ lazy }里也可以
import { Router, Switch, Route } from 'react-router';
import { createBrowserHistory } from 'history';
import '@/app.less';

const historyInstance = createBrowserHistory();
const Home = React.lazy(() => import('pages/home/index'));
const App = () => (
    <Router history={historyInstance}>
        <Suspense fallback={<p>loading</p>}>
            <Switch>
                <Route exact path='/' component={Home} />
            </Switch>
        </Suspense>
    </Router>
);
export default App;
  1. 特点:
    (1)没有在内置支持 delay 功能,因此,即使加载工程只需要几毫秒的时间, fallback也会被执行;
    (2)即:每个页面出来之前都会先加载loading组件;

三、添加Error Boundary

  • 思想:当组件发生错误时,即抛出错误(throw error),会直接进入static getDerivedStateFromError()生命周期,从而显示Error Boundary组件相应的error UI。
  • 顺序:页面组件出错 --- static getDerivedStateFromError()---componentDidCatch()---错误callback UI

ErrorBoundary组件代码附上:

import React, { Component } from 'react';
import PropTypes from 'prop-types';

class ErrorBoundary extends Component {
    constructor() {
        super();
        this.state = {
            errorStatus: false
        };
    }

    static getDerivedStateFromError() { 
        // 接受一个参数error,和底下的didcatch的error一样
       // throw new Error抛出会立马捕捉到,并处理
        return {
            errorStatus: true
        };
    }

    componentDidCatch(error, info) {
        // You can also log the error to an error reporting service
        console.info(error, info);
    }

    render() {
        const { errorStatus } = this.state;
        const { children } = this.props;
        if (errorStatus) {
            return <div>error</div>;
        }
        return children;
    }
}
ErrorBoundary.propTypes = {
    children: PropTypes.shape({}).isRequired
};
export default ErrorBoundary;

App组件:

import React, { Suspense } from 'react';
import { Router, Switch, Route } from 'react-router';
import { createBrowserHistory } from 'history';
import { ErrorBoundary, Com1 } from 'components/index';
import '@/app.less';

const historyInstance = createBrowserHistory();
const Home = React.lazy(() => import('pages/home/index'));

const App = () => (
    <Router history={historyInstance}>
        <ErrorBoundary>         /*错误边界组件*/
            <Suspense fallback={<p>loading</p>}>
                <Switch>
                    <Route exact path='/' component={Home} />
                    <Route path='/next' component={Com1} />
                </Switch>
            </Suspense>
        </ErrorBoundary>
    </Router>
);
export default App;

四、支持箭头函数语法

  1. 为了支持箭头函数的写法,并在函数里面使用组件类中的this,可以避免每次需要使用bindthis和函数绑定。基于此,需要新加插件,即:安装npm i -D @babel/plugin-proposal-class-properties

    对比:
handleClick() {
  // 拿不到this:undefined
}
render() {
   return (
        <div>
            <Button type="primary" onClick={this.handleClick}>按钮</Button>
        </div>
   );
}
handleClick() {
  // 可以拿到this
}
render() {
   return (
        <div>
            <Button type="primary" onClick={this.handleClick.bind(this)}>按钮</Button>
        </div>
   );
}
handleClick = () => {
  // 可以拿到this
}
render() {
   return (
        <div>
            <Button type="primary" onClick={this.handleClick}>按钮</Button>
        </div>
   );
  1. 安装之后,并在babel.config.js里配置plugin,再次运行正常。
// plugins 在 presets 前执行
module.exports = {
    // plugins 加载顺序,数组从前往后
    plugins: [
        '@babel/plugin-syntax-dynamic-import', // 支持 `() => import('./Home')` 语法
        ['@babel/plugin-proposal-class-properties', { loose: true }], // 支持 `handleChange = () => {}` 语法
        ['babel-plugin-import', { libraryName: 'antd', style: true }] // 按需加载 `antd` 组件, `style: true` 会加载 less 文件
    ],
    // presets 加载顺序,数组从后往前
    presets: ['@babel/react'],
};

五、 整理文件,添加router文件

将使用React.lazy加载的页面都放在 router/index.js文件下,统一配置,如:

import { lazy } from 'react';

const Home = lazy(() => import('pages/home/index'));
const routes = [
    {
        name: 'home',
        path: '/',
        component: Home
    }
];
export default routes;

app.js就可以循环显示了,如:

import React, { Suspense } from 'react';
import { Router, Switch, Route } from 'react-router';
import { createBrowserHistory } from 'history';
import { ErrorBoundary, Loading } from 'components/index';
import '@/app.less';
import routes from 'router/index';

const historyInstance = createBrowserHistory();
const App = () => (
    <Router history={historyInstance}>
        <ErrorBoundary>
            <Suspense fallback={<Loading />}>
                <Switch>
                    {
                        routes.map(item => (
                            <Route exact key={item.path} path={item.path} component={item.component} />
                        ))
                    }
                </Switch>
            </Suspense>
        </ErrorBoundary>
    </Router>
);
export default App;

以上,本部分完成。

相关文章

网友评论

      本文标题:按需加载

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