zoukankan      html  css  js  c++  java
  • React 性能优化之组件动态加载(react-loadable)

    React 项目打包时,如果不进行异步组件的处理,那么所有页面所需要的 js 都在同一文件中(bundle.js),整个js文件很大,从而导致首屏加载时间过长。


    所有,可以对组件进行异步加载处理,通常可以使用 React-loadable

    React-loadable 使用

    例如,对于项目中的detail组件(/src/pages/detail/),在 detail 目录下新建 loadable.js:

    import React from 'react';
    import Loadable from 'react-loadable';
    
    const LoadableComponent = Loadable({
      loader: () => import('./index.js'),
      loading() {
          return <div>正在加载</div>
      },
    });
    
    export default () => <LoadableComponent/>
    

    然后在 app.js 里面引入detail组件:

    // 不适用 react-loadable 时的引入方式:
    // import Detail from './pages/detail/index';
    
    
    // 使用 react-loadable 时的引入方式:
    import Detail from './pages/detail/loadable';
    
    ... ...
    
    class App extends Component {
      render() {
        return (
          <Provider store={store}>
            <Fragment> 
              <BrowserRouter>
                ··· ···
                    <Route path='/detail/:id' exact component={Detail}></Route>
                ··· ···
              </BrowserRouter>
            </Fragment>
          </Provider>
        )
      }
    }
    

    但是,在/pages/detail/index.js文件中,如果想访问到当前路由的 match,location,history对象,就访问不到了

    需要使用 withRouter 对 /detail/index.js 作如下处理:

    import { withRouter } from 'react-router-dom'; 
    
    class Detail extends Component {
        render() {
            ··· ···
        }
    
        componentDidMount() {
            // withRouter处理后,就可以在这里拿到 match 对象了
            console.log(this.props.match); 
            this.props.getDetail(this.props.match.params.id);
        }
    }
     
    ··· ···
    
    export default connect(mapStateToProps, mapDispatchToProps)(withRouter(Detail));
    

    withRouter 可以将一个非路由组件包裹为路由组件,使这个非路由组件也能访问到当前路由的match, location, history对象。

    统一处理

    上面已经实现了动态加载 detail 组件的方式,但是如果有多个组件时,需要在每个组件下新建 loadable.js ,比较麻烦,所有可以统一封装处理所有组件的动态加载。

    新建目录/src/utils,新建文件 /src/utils/loadable.js

    import React from 'react';
    import Loadable from 'react-loadable';
    
    export default (loader) => {
        return Loadable({
            loader,
            loading() {
                return <div>正在加载</div>
            },
        });
    }
    

    在 app.js 中,

    import loadable from './utils/loadable';
    import Header from './common/header'; 
    
    <!--异步加载组件-->
    const Home = loadable(() => import('./pages/home'));
    const Detail = loadable(() => import('./pages/detail'));
    const Login = loadable(() => import('./pages/login'));
    const Write = loadable(() => import('./pages/write'));
      
    class App extends Component {
    
      render() {
        return (
          <Provider store={store}>
            <Fragment> 
              <BrowserRouter>
                <div>
                  <Header />
                  <Switch>
                    <Route
                      exact
                      path="/"
                      render={() => <Redirect to="/home" />}
                    />
                    <Route path='/home' exact component={Home}></Route>
                    <Route path='/login' exact component={Login}></Route>
                    <Route path='/write' exact component={Write}></Route>
                    <Route path='/detail/:id' exact component={Detail}></Route>
                    <Route render={() => <div>Not Found</div>} />
                  </Switch>
                </div>
              </BrowserRouter>
            </Fragment>
          </Provider>
        )
      }
    }
    
    export default App;
    
  • 相关阅读:
    AtCoder Grand Contest 015 题解
    AtCoder Grand Contest 014 题解
    AtCoder Grand Contest 013 题解
    AtCoder Grand Contest 012 题解
    AtCoder Grand Contest 011 题解
    AtCoder Grand Contest 010 题解
    AtCoder Grand Contest 009 题解
    NOIP2017 Day2 题解
    博客园主题备份
    多项式全家桶
  • 原文地址:https://www.cnblogs.com/cckui/p/11492510.html
Copyright © 2011-2022 走看看