3-8 异步组件以及 withRouter 路由方法的使用

目前我们的项目,是单页面程序。第一次加载的时候,是把所有的组件都加载了的。当项目很大的时候,首屏时间可能会变得很长。

我们可以使用异步组件来解决这个问题。我们可以用封装起来的第三方模块来实现,这样会没那么复杂。

react-loadable

我们可以在 github 找到它 https://github.com/jamiebuilds/react-loadable

先下载到项目吧

yarn add react-loadable

下面我们来实现,详情页面的代码,是当我们进入详情页面才会被加载。

我们在 src/pages/detail 下创建一个文件 loadable.js 如下。

loader 是指,我们要异步加载哪个组件。loading 是指在异步等待的过程中要显示的组件内容,这里用的是JSX 语法,因此要引入React。最后,我们把这个组件当一个无状态组件返回。它就能实现异步加载的功能。

import React from 'react';
import Loadable from 'react-loadable';

const LoadableComponent = Loadable({
  loader: () => import('./'),
  loading () {
      return <div>正在加载</div>
  },
});

export default () => <LoadableComponent />

接着,我们还要来改一下 src/App.js

将以前的Detail 组件变为这个异步组件。如下。

import React, { Component } from 'react';
import { BrowserRouter, Route } from 'react-router-dom';
import { Provider } from 'react-redux';
import { GlobalStyle } from './style.js';
import Header from './common/header';
import store from './store/index';
import Home from './pages/home';
import Detail from './pages/detail/loadable';
import Login from './pages/login';
import WriteArticle from './pages/write';

class App extends Component {
  render() {
    return (
      <div>
        <GlobalStyle />
        <Provider store={store}>
        <div>
          <BrowserRouter>
            <Header />
            <Route path='/' exact component={Home}></Route>
            <Route path='/login' exact component={Login}></Route>
            <Route path='/write' exact component={WriteArticle}></Route>
            <Route path='/detail/:id' exact component={Detail}></Route>
          </BrowserRouter>
        </div>
        </Provider>
      </div>
    );
  }
}

export default App;

这个时候,我们去进入详情也,是会报错的。因为在详情页获得url 中 id 的值的话,这个时候是异步组件才能获得的。而我们在 Detail 中写了获取id 值的代码。

我们可以用过withRouter 方法解决这个问题。最后一行代码withRouter(Detail) 意思是,使Detail 组件有能力获得路由的所有参数和内容。

import React, {PureComponent} from 'react';
import { withRouter } from 'react-router-dom';
import { connect } from 'react-redux';
import { DetailWrapper,
    Header,
    Content
 } from './style';
 import { actionCreators } from './store';
 
class Detail extends PureComponent {
    render () {
        const { title, content } = this.props;
        return (
            <DetailWrapper>
                <Header>
                    { title }
                </Header>
                <Content dangerouslySetInnerHTML={{__html: content}}>
                </Content>
            </DetailWrapper>
        )
    }
    componentDidMount () {
        this.props.getDetail(this.props.match.params.id);
    }
}
 
const mapState = (state) => {
    return {
        title: state.get("detail").get("title"),
        content: state.get("detail").get("content")
    }
}

const mapDispatch = (dispatch) => {
    return {
        getDetail (id) {
            const action = actionCreators.getDetail(id);
            dispatch(action);
        }
    }
}
 
export default connect(mapState, mapDispatch)(withRouter(Detail));

Done!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值