react-router-4官方文档
demo的github源码地址
URL
一个URL可以定位到网络上的指定资源。一个典型URL结构如下:
虽然protocol和hostname的组合可以直接让我们访问特定的网站,但是pathname则代表的是这个网站上的指定资源。
举个例子,看看如下的一个访问音乐网站的URL
https://example.com.com/artists/87589/albums/1758221
这个地址可以访问特定艺术家的专辑。该URL包含了艺术家以及它的专辑的标识符:
example.com/artists/:artistId/albums/:albumId
在一个传统的,只有很少的JavaScript的页面应用中,对网页访问的请求流程大致如下:
- 浏览器要访问页面,向服务器发送请求
- 服务器根据URL中的标识符从数据库中获取artist和album的数据
- 服务器将获取后的数据拼接成模板
- 服务器返回模板字符串,并且返回其关联的资源文件,例如CSS文件和图片文件等
- 浏览器将得到的资源渲染
当我们使用React,我们想要React来生成这样的页面。所以,使用React的请求流程就会大致如下:
- 浏览器要访问页面,向服务器发送请求
-
服务器不关心pathname。取而代之的是,它仅仅返回一个标准的
index.html
,其中包含了React app和其他静态资源文件 - React app 挂载
- React app抽取出URL中标识符,并且使用这些标识符来生成API调用以从artist和album中获取数据
- React根据API调用后抓取的数据渲染页面
单页应用(Single-page applications/ SPA)
是加载一次然后通过JavaScript动态更新页面上的元素的应用。React通过路由能够很容易的实现单页应用。
实现
首先生成我们的demo,一个新闻页面切换的app
create-react-app react-router-demo
并且成功运行项目。
目录结构如下:
要使用React的路由功能,需要安装依赖react-router
。这里我们使用第四个版本的 react-router
。
安装依赖:
yarn add react-router-dom
或者
npm install --save react-router-dom
在router.js中:
import React from 'react';
import {BrowserRouter, Route, Link} from 'react-router-dom'
import News from '../components/News'
import NBA from '../components/NBA'
import Economics from '../components/Economic'
const router = (
<BrowserRouter>
<div>
<h2>news app</h2>
<ul>
<li>
<Link to="/">news</Link>
</li>
<li>
<Link to="/nba">nba</Link>
</li>
<li>
<Link to="/economics">economics</Link>
</li>
</ul>
<Route path="/" component={News} exact></Route>
<Route path="/nba" component={NBA}></Route>
<Route path="/economics" component={Economics}></Route>
</div>
</BrowserRouter>
)
export default router
然后点击对应的链接就能切换响应的页面了。
现在需要点击对应的链接后,能够有一个显示点击后的效果。这个时候就需要使用NavLink
了。
如下:
<style>
.is-active {
font-weight: bold;
color: deepskyblue;
}
</style>
const router = (
<BrowserRouter>
<div>
<h2>news app</h2>
<ul>
<li>
<NavLink to="/" activeClassName="is-active" exact>news</NavLink>
</li>
<li>
<NavLink to="/nba" activeClassName="is-active">nba</NavLink>
</li>
<li>
<NavLink to="/economics" activeClassName="is-active">economics</NavLink>
</li>
</ul>
<Route path="/" component={News} exact></Route>
<Route path="/nba" component={NBA}></Route>
<Route path="/economics" component={Economics}></Route>
</div>
</BrowserRouter>
)
这样,点击对应的链接后,该链接会显示style
中的样式。
当用户输入错了URL地址,我们希望能够跳转到一个页面不存在的通用的页面。我们新建一个NotFound的组件,再在路由中是 Switch
。表示只要匹配到第一个就跳转到对应组件。
const router = (
<BrowserRouter>
<div>
<h2>news app</h2>
<ul>
<li>
<NavLink to="/" activeClassName="is-active" exact>news</NavLink>
</li>
<li>
<NavLink to="/nba" activeClassName="is-active">nba</NavLink>
</li>
<li>
<NavLink to="/economics" activeClassName="is-active">economics</NavLink>
</li>
</ul>
<Switch>
<Route path="/" component={News} exact></Route>
<Route path="/nba" component={NBA}></Route>
<Route path="/economics" component={Economics}></Route>
<Route component={NotFound}></Route>
</Switch>
</div>
</BrowserRouter>
)
这样,当用户虽然输入一个URL地址后,只要没有匹配到前面的路由地址,那么就会跳转到NotFound页面。
路由参数
当我们想要访问一个新闻列表的页面,新闻列表中有很多个新闻,我们点击其中的新闻,则URL地址可能如下:
localhost:3000/news/1
localhost:3000/news/2
localhost:3000/news/3
当有大量新闻的时候,为每个新闻都写一个组件显然是不显示的。这时候就可以使用路由参数。
router.js
const router = (
<BrowserRouter>
<div>
<h2>news app</h2>
<ul>
<li>
<NavLink to="/" activeClassName="is-active" exact>news</NavLink>
</li>
<li>
<NavLink to="/nba" activeClassName="is-active">nba</NavLink>
</li>
<li>
<NavLink to="/economics" activeClassName="is-active">economics</NavLink>
</li>
</ul>
<Switch>
<Route path="/" component={News} exact></Route>
<Route path="/nba" component={NBA}></Route>
<Route path="/economics" component={Economics}></Route>
<Route path="/newslist/:id" component={NewsList}></Route>
<Route component={NotFound}></Route>
</Switch>
</div>
</BrowserRouter>
)
NewsList.js
class NewsList extends Component {
render () {
return (
<div>
newslist-item {this.props.match.params.id}
</div>
)
}
}
这样,主要输入形如如下的网址,那么就可以切换到不同的NewsList中的新闻了:
localhost:3000/news/id