前言
之前发现了蚂蚁金服的 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
来源: https://juejin.im/entry/5b150b246fb9a01e5d32e91a