从零开始React + Dva + ant.design开发项目—路由

5,825 阅读3分钟
原文链接: www.divpc.cn

前言

之前发现了蚂蚁金服的ant.design,感觉这个框架有完整的设计交互规范,组件库丰富,交互友好,代码质量高,稳定性好,然后就一直想要在项目中使用下这个框架,但是之前一直都是用VUE的不怎么会React。今天学习了下怎么去使用React以及Dva,在学习的过程中碰到了以下几个路由相关的问题:

  1. 如何嵌套路由
  2. 如何设置动态路由
  3. 如何异步加载页面

今天我在这里主要是解决这些问题,就不讲相关的基本知识,基本知识不过关的建议大家去https://github.com/dvajs/dva-knowledgemap学习相关知识的最小集。这样帮助大家学习最少的知识最快学会如何使用React + DVA来做项目。

项目初始化

按照ant的官网(https://ant.design/docs/react/practical-projects-cn)的步骤生成一个项目

  1. 安装dva脚手架:npm install dva-cli -g
  2. 创建一个新应用:dva new dva-demo
  3. 进入新生成的应用内:cd dva-demo
  4. 启动应用:npm start;几秒后你就可以看到欢迎页面了
  5. 配置按需加载antd:npm install antd babel-plugin-import -D后修改根目录下的.webpackrc文件,增加如下代码:
{
  "extraBabelPlugins": [
    ["import", { "libraryName": "antd", "libraryDirectory": "es", "style": "css" }]
  ]
}

  1. 重新启动项目:npm start

嵌套路由

  1. 在src/routes创建父页面news.js:
import React from 'react';
import { connect } from 'dva';

function News() {
  return (
    <div>我是新闻页面</div>
  );
}

export default connect()(News);

  1. 在src/routes创建子页面newsList.js:
import React from 'react';
import { connect } from 'dva';

function NewsList() {
  return (
    <div>我是新闻列表页面</div>
  );
}

export default connect()(NewsList);
  1. 在src/router.js中增加news页面:
import React from 'react';
import { Router, Route, Switch } from 'dva/router';
import IndexPage from './routes/IndexPage';
import News from './routes/news';

function RouterConfig({ history }) {
  return (
    <Router history={history}>
      <Switch>
        <Route path="/" exact component={IndexPage} />
        <Route path="/news" component={News} />
      </Switch>
    </Router>
  );
}

export default RouterConfig;

  1. 修改src/routes/news.js页面,在news页面中增加子页面的声明:
import React from 'react';
import { Route } from 'dva/router';
import { connect } from 'dva';
import NewsList from './newsList';

function News({match}) {
  return (
    <div>
      <span>我是新闻页面</span>
      <Route path={`${match.url}/list`} exact component={NewsList}></Route>
    </div>
  );
}

export default connect()(News);

这个时候你在浏览器中输入:http://localhost:8000/#/news/list就可以看到:
我是新闻页面
我是新闻列表页面

动态路由

  1. 在src/routes新增页面newsDetail.js:
import React from 'react';
import { connect } from 'dva';

function NewsDetail({match}) {
  return (
    <div>
      我是新闻详情页面{match.params.id}
    </div>
  );
}

export default connect()(NewsDetail);
  1. 修改src/routes/news.js页面,在news页面中增加子页面的声明:
import React from 'react';
import { Route } from 'dva/router';
import { connect } from 'dva';
import NewsList from './newsList';
import newsDetail from './newsDetail';

function News({match}) {
  return (
    <div>
      <span>我是新闻页面</span>
      <Route path={`${match.url}/list`} exact component={NewsList}></Route>
      <Route path={`${match.url}/detail/:id`} exact component={newsDetail}></Route>
    </div>
  );
}

export default connect()(News);

  1. 访问http://localhost:8000/#/news/detail/1你会看到:
    我是新闻页面
    我是新闻详情页面1

异步加载页面

异步加载页面的功能主要是参考博客:https://www.jianshu.com/p/dc867f5d28b1 解决的,我在这里主要是帮助大家快速解决问题,如果大家对具体的实现感兴趣,可以去看看这篇文章。

  1. 首先在src/utils下新建工具类asyncComponent.js,用来异步加载组件:
import React, { Component } from "react";

export default function asyncComponent(importComponent) {
  class AsyncComponent extends Component {
    constructor(props) {
      super(props);

      this.state = {
        component: null
      };
    }

    async componentDidMount() {
      const { default: component } = await importComponent();

      this.setState({
        component: component
      });
    }

    render() {
      const C = this.state.component;

      return C ? <C {...this.props} /> : null;
    }
  }

  return AsyncComponent;
}
  1. 修改各个导入页面的方式: src/router.js中
import IndexPage from './routes/IndexPage';
import News from './routes/news';

变成

import asyncComponent from './utils/asyncComponent.js';
const IndexPage = asyncComponent(() => import('./routes/IndexPage'));
const News = asyncComponent(() => import('./routes/news'));

src/routes/news.js:

import NewsList from './newsList';
import newsDetail from './newsDetail';

变成

import asyncComponent from '../utils/asyncComponent.js';
const NewsList = asyncComponent(() => import('./newsList'));
const newsDetail = asyncComponent(() => import('./newsDetail'));

大功告成,这样就可以实现页面的异步加载了,同样的咱们的页面其实也是Reac的一个组件,所以这个方法还可以用来异步加载其他的组件。

参考文章

React-Router 4.2 的嵌套路由实现:https://blog.csdn.net/arsiya_jerry/article/details/78122827
react-router 4.x的异步组件加载(Code Splitting):https://www.jianshu.com/p/dc867f5d28b1