使用react-router实现单页面应用路由
这是Webpack+React系列配置过程记录的第二篇。其他内容请参考:
- 第一篇:使用webpack、babel、react、antdesign配置单页面应用开发环境
- 第二篇:使用react-router实现单页面应用路由
- 第三篇:优化单页面开发环境:webpack与react的运行时打包与热更新
- 第四篇:React配合Webpack实现代码分割与异步加载
上一篇文章讲述了如何搭建单页面应用的开发环境。本文接着介绍如何实现单页面应用。
实际上,单页面应用利用js实现了页面的动态化,用户使用时基本感知不到网页是如何实现的,开发也不应该让用户感知到。为了实现这一步,react提供了一个官方的路由组件react-router,让你的单页面应用支持页面的跳转以及动态渲染。
使用react-router的前端实现
安装react-router
npm install --save react-router-dom
我使用的是最新版本4.1.1,这个版本的react-router针对浏览器、原生应用等环境已经做了区分。我做的是基于web的单页面应用,因此安装的时候我使用的是react-router-dom这个依赖。
使用react-router
还是基于上一篇文章搭建的开发环境,我们使用官方示例简单入门对react-router的使用方法。
回顾一下上一篇文章的开发环境:

这里主要需要修改index.js,其内容改为官方示例代码:
import React from 'react';
import ReactDOM from 'react-dom';
import {
BrowserRouter as Router,
Route,
Link
} from 'react-router-dom'; const BasicExample = () => (
<Router>
<div>
<ul>
<li><Link to="/">Home</Link></li>
<li><Link to="/about">About</Link></li>
<li><Link to="/topics">Topics</Link></li>
</ul> <hr/> <Route exact path="/" component={Home}/>
<Route path="/about" component={About}/>
<Route path="/topics" component={Topics}/>
</div>
</Router>
) const Home = () => (
<div>
<h2>Home</h2>
</div>
) const About = () => (
<div>
<h2>About</h2>
</div>
) const Topics = ({ match }) => (
<div>
<h2>Topics</h2>
<ul>
<li>
<Link to={`${match.url}/rendering`}>
Rendering with React
</Link>
</li>
<li>
<Link to={`${match.url}/components`}>
Components
</Link>
</li>
<li>
<Link to={`${match.url}/props-v-state`}>
Props v. State
</Link>
</li>
</ul> <Route path={`${match.url}/:topicId`} component={Topic}/>
<Route exact path={match.url} render={() => (
<h3>Please select a topic.</h3>
)}/>
</div>
) const Topic = ({ match }) => (
<div>
<h3>{match.params.topicId}</h3>
</div>
) ReactDOM.render(<BasicExample/>, document.getElementById('main'));
注意到上面的代码引入了react-router的BrowserRouter(重命名为Router),Route,Link三个组件。新版本的react-router提出了一切都以Component实现的原则,因此这些组件实际上都是React.Component的实现。
BrowserRouter是一个容器Component,其内部实现了路由跳转的逻辑。旧版本直接使用Router就可以,新版本根据环境不同有不同的实现,Web环境使用BrowserRouter。
Route也是一个Component,配置了页面路径以及当用户输入的路径命中时需要渲染的组件。
Link用于跳转,有点像HTML的a标签。不一样的是Link是需要在后端进行编译,最终可能以a标签的形式呈现给用户。
验证react-router
使用下面命令编译并运行应用:
npm run build
npm start
访问http://localhost:2000 可以看到页面已经可以正常访问,且点击可以实现页面跳转。

如果你细心一点,你会发现刚刚访问的页面链接是使用a标签出发了页面的跳转。但是跳转后页面并没有向后端发送页面请求。事实上,这就是单页面应用为了解耦前后端实现的目标之一。
我在index.js中使用Link组件,编译后在浏览器上以a标签呈现给用户。而react-router连接了这些a标签的事件处理,动态的实现组件的渲染和浏览器地址栏内容的修改。因此这个过程不需要重新加载内容也不会向后端发出网络请求。
使用react-router的后端实现
单页面是为了实现前后端的业务解耦,但绝对的解耦是不存在的。有两个方面佐证这个观点。首先是api协议的约定,这必须要前端与后端的同时支持;其次就是本文的主要内容——路由实现。
缺少后端支持的问题
通过上面内容我们知道单页面应用的路由是通过js实现的,相对于传统网站而言是“伪跳转”。那么如果用户直接在浏览器上输入http://localhost:2000/about 然后回车会有什么效果。
使用我的demo环境,会看到下图:
果断的404响应。因为我的服务器根本没有/about这个目录或者文件。
增加后端支持
为了解决这个问题,我需要增加这样一个依赖:
npm install --save connect-history-api-fallback
并且在项目根目录的index.js(注意不是public目录的index.js,这里应该重新命名一下的,当前将就一下)。
内容改为:
var express = require('express');
var app = express();
app.use('/', require('connect-history-api-fallback')()); // Add
app.use('/', express.static('public'));
var server = app.listen(2000, function() {
var port = server.address().port;
console.log('Open http://localhost:%s', port);
});
另外需要修改一下public目录下的index.html文件的内容。这是使用相对路径获取js文件,属于上次留下来的bug,不改的话会存在问题。内容如下:
<html>
<head>
</head>
<body>
<p>Hello world</p>
<div id='main'></div>
<script src="/out.js"></script><!-- 改动行 -->
</body>
</html>
这样就可以解决问题了。重新在浏览器输入http://localhost:2000/about 可以看到页面显示正常了。
需要注意增加的代码必须放在express.static行的上方。这涉及的express框架的原理,不在这里深究,只要知道connect-history-api-fallback组件根据配置,帮我们把public目录下的index.html作为所有不存在的路径的请求的响应返回给浏览器。
使用react-router实现单页面应用路由的更多相关文章
- vue-router(配置子路由--单页面多路由区域操作)
1.配置子路由: import Post from "@components/Post" export default new Router({ routers:[ { path: ...
- react router 4.0以上的路由应用
thead>tr>th{padding:8px;line-height:1.4285714;border-top:1px solid #ddd}.table>thead>tr& ...
- Vue 子路由 与 单页面多路由 的区别
本文地址:http://www.cnblogs.com/veinyin/p/7911292.html 最近学完了基础课程,打算整理一波笔记,对基本概念梳理一遍,惊觉对子路由和单页面多路由混淆的一塌糊涂 ...
- nignx部署Vue单页面刷新路由404问题解决
官网说明: https://router.vuejs.org/zh/guide/essentials/history-mode.html#%E8%AD%A6%E5%91%8A 在linux下搭建ngi ...
- React+React Router+React-Transition-Group实现页面左右滑动+滚动位置记忆
2018年12月17日更新: 修复在qq浏览器下执行pop跳转时页面错位问题 本文的代码已封装为npm包发布:react-slide-animation-router 在React Router中,想 ...
- Angular——单页面与路由的使用
单页面 SPA(Single Page Application)指的是通单一页面展示所有功能,通过Ajax动态获取数据然后进行实时渲染,结合CSS3动画模仿原生App交互,然后再进行打包(使用工具把W ...
- vue-cli利用router创建单页面
一.创建脚手架 第一步 打开命令输入vue init webpack-simple vue-name 下载webpack-simple (vue-name是你要创建的项目名称) 第二步 输入cd v ...
- React框架搭建单页面应用package.json基本包和依赖包
{ //依赖包 "devDependencies": { //babel "babel-core": "6.24.1", "bab ...
- 优化单页面开发环境:webpack与react的运行时打包与热更新
前面两篇文章介绍初步搭建单页面应用的开发环境: 第一篇:使用webpack.babel.react.antdesign配置单页面应用开发环境 第二篇:使用react-router实现单页面应用路由 这 ...
随机推荐
- 2017"百度之星"程序设计大赛 - 资格赛【1001 Floyd求最小环 1002 歪解(并查集),1003 完全背包 1004 01背包 1005 打表找规律+卡特兰数】
度度熊保护村庄 Accepts: 13 Submissions: 488 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/3276 ...
- 2016 USP-ICMC-Codeforces-Gym101063C-Sleep Buddies Gym101063F-Bandejao Gym101063J-The Keys
Gym101063C-Sleep Buddies It is nighttime in the Earth Colony on Mars and everyone is getting ready t ...
- BZOJ1786: [Ahoi2008]Pair 配对/1831: [AHOI2008]逆序对
这两道题是一样的. 可以发现,-1变成的数是单调不降. 记录下原有的逆序对个数. 预处理出每个点取每个值所产生的逆序对个数,然后dp转移. #include<cstring> #inclu ...
- 如何为图片添加热点链接?(map + area)
所谓图片热点链接就是为图片指定一个或多个区域以实现点击跳转到指定的页面.简单来说就是点击某一区域就能跳转到相应的页面,而无需点击整个图片才能跳转. 说到图片热点链接,我首先想到了map + area, ...
- JavaScrip 排序算法
转自: http://blog.givebest.cn/javascript/2017/08/02/javascript-sorting-algorithms.html 基础构造函数 以下几种排序算法 ...
- PHP开发api接口安全验证
php的api接口 在实际工作中,使用PHP写api接口是经常做的,PHP写好接口后,前台就可以通过链接获取接口提供的数据,而返回的数据一般分为两种情况,xml和json,在这个过程中,服务器并不知道 ...
- linux 巨页使用测试以及勘误1
linux使用hugetlbfs的方式来支持巨页,也成为大页. 网上看到有人说巨页不支持read,和write调用,只支持mmap,但是看3.10内核代码的时候发现: const struct fil ...
- PHP数据核心:Zend HashTable详解
最近看了篇关于php内的hashtable的文章,PHP数据存储的核心,各种常量.变量.函数.类.对象等都用它来组织的.转载地址 http://www.phppan.com/2009/12/zend- ...
- Altium designer知识总结
原理图库文件 =原理图元件库 .schlibPCB库文件=封装库.pcblib 集成库=原理图库文件+封装库 .intlib
- C语言学习之交换(冒泡)排序
在学习c语言的过程中,在数组内容中我们总是能学习到对一组数据进行排序,对于排序有许多的方法,像 (交换)冒泡排序.选择排序.(基数)桶排序.(插入)二分法排序等等. 我主要以我个人的理解去分析常见的交 ...