前言
之前发现了蚂蚁金服的ant.design,感觉这个框架有完整的设计交互规范,组件库丰富,交互友好,代码质量高,稳定性好,然后就一直想要在项目中使用下这个框架,但是之前一直都是用VUE的不怎么会React。今天学习了下怎么去使用React以及Dva,在学习的过程中碰到了以下几个路由相关的问题:
- 如何嵌套路由
- 如何设置动态路由
- 如何异步加载页面
今天我在这里主要是解决这些问题,就不讲相关的基本知识,基本知识不过关的建议大家去https://github.com/dvajs/dva-knowledgemap学习相关知识的最小集。这样帮助大家学习最少的知识最快学会如何使用React + DVA来做项目。
项目初始化
按照ant的官网(https://ant.design/docs/react/practical-projects-cn)的步骤生成一个项目
- 安装dva脚手架:npm install dva-cli -g
- 创建一个新应用:dva new dva-demo
- 进入新生成的应用内:cd dva-demo
- 启动应用:npm start;几秒后你就可以看到欢迎页面了
- 配置按需加载antd:npm install antd babel-plugin-import -D后修改根目录下的.webpackrc文件,增加如下代码:
{
"extraBabelPlugins": [
["import", { "libraryName": "antd", "libraryDirectory": "es", "style": "css" }]
]
}
- 重新启动项目:npm start
嵌套路由
- 在src/routes创建父页面news.js:
import React from 'react';
import { connect } from 'dva';
function News() {
return (
<div>我是新闻页面</div>
);
}
export default connect()(News);
- 在src/routes创建子页面newsList.js:
import React from 'react';
import { connect } from 'dva';
function NewsList() {
return (
<div>我是新闻列表页面</div>
);
}
export default connect()(NewsList);
- 在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;
- 修改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就可以看到:
我是新闻页面
我是新闻列表页面
动态路由
- 在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);
- 修改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);
- 访问http://localhost:8000/#/news/detail/1你会看到:
我是新闻页面
我是新闻详情页面1
异步加载页面
异步加载页面的功能主要是参考博客:https://www.jianshu.com/p/dc867f5d28b1 解决的,我在这里主要是帮助大家快速解决问题,如果大家对具体的实现感兴趣,可以去看看这篇文章。
- 首先在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;
}
- 修改各个导入页面的方式: 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