# 什么是路由?

路由是根据不同的url地址展示不同的内容或页面。 一个针对React而设计的路由解决方案、可以友好的帮你解决React componentsURl之间的同步映射关系。

示例网站: react-router示例

# 路由安装

npm install react‐router‐dom

# 路由使用

  1. 路由导入

路由导入方法

  1. 定义路由及重定向

定义路由及重定向

使用Redirect进行路由重定向匹配,由于是贪婪匹配,在上面例子中,如果已经匹配到了center路由,此时刷新页面会继续匹配到**/**根路由。

所以一般在使用HashRouter时配套使用Switch,匹配到路由之后立马跳出,只能匹配到第一个符合条件的路由。

# HashRouter与BrowserRouter的异同

HashRouter的特点:localhost:3000/#/film

  1. HashRouter在路径中包含了**#,相当于锚点定位,因此不论#**后面的路径怎么变化,请求的都相当于是#之前的那个页面,可以很容易的进行前后端不分离的部署(也就是把前端打包后的文件放到服务器端的public或static里)。

  2. 这个警告只有在hash 模式会出现(因为Hash模式下,默认浏览器不会记录重复点击的路由记录),在NavLink 加上 replace 来解决,但轻易不要使用。(此警告并无大碍)

BrowserRouter的特点也是弊端:localhost:3000/flim

因为BrowserRouter模式下请求的链接都是ip地址: 端口/xxxx/xxxx,因此相当于每个URL都会访问一个不同的后端地址,如果后端没有覆盖到路由就会产生404错误。

解决方案:加入中间件解决,放在服务器端路由匹配的最后,如果前面的API接口都不匹配,则返回index. html页面。但这样也有一些小问题,因为要求前端路由和后端路由的URL不能重复。

比如商品列表组件叫/product/list,而请求商品列表的API也是/product/list,那么就会访问不到页面,而是被API接口匹配到。

# 嵌套路由(父子关系的路由)

定义在 src/Router/index. js 根路由里,当路由组件多的时候不利于维护

所以我们最好在,父子路由需要嵌套的时候,把子路由写在父路由里,比如,我写的组件顺序是App、Film(Nowplaying, Comingsoon)、Cinema、Centerflim路由包括nowplaying,comingsoon路由,我们就把这两个分路由,定义在flim路由组件里。

# 路由跳转方式

  1. 声明式导航 NavLink根据className判断自带高亮效果

声明式导航

  1. 编程式导航:通过**this.props.history.push()**跳转路由

编程式导航

如果想要做列表页路由跳转详情页面路由,步骤是:

  1. 先在列表页nowplaying取得每条信息的id值,
  2. 在根路由配置 详情页面的myid
  3. 根据不同的myid跳转不同的详情页路由

步骤1:

编程式导航

步骤2:

步骤3:

注释: 此时的myid属性,是由根路由层,包裹的Route传递过来的,而并非父亲组件传递 此时的myid属性,是列表页(nowplaying) map遍历的数组每一项

使用React-devtools扩展工具,可以看到myid是从最一开始的Route包裹传递的。

我们再来看一下,Route还能给它包裹的组件传递什么东西?

  • this. props. history. go(-1) 回到上一个页面 ,回退几层
  • this. props. history. goBack( ) 回退页面
  • this. props. history. goForward( ) 前进页面

# 公共组件抽离之后的路由跳转

# 方法一 - 父组件传值

遇到上图这种的,正在热映模块和即将上映模块结构类似的组件时,我们可以把nowplaying和comingsoon组件中,重复的li部分提取成公共组件FilmItem后,再引入时,就需要在FilmItem组件上再次传递this. props. history属性

当然也可以简写成

<FilmItem key={item} item={item} {... this. props}></FilmItem>

这样我们又可以在封装之后的FilmItem里继续跳转路由了

# 方法二 - 高阶组件(withRouter)

在后面。我们会详细介绍高阶组件,可以简单理解为 高阶组件为其包裹组件包裹生成了一个干爹组件,把需要的属性,我们传递进来。

# 路由传参

1this. props. history. push({ pathname : '/user' , query : { day: 'Friday'} })
// 通过下面这个接收到参数
this. props. location. query. day

(2this. props. history. push({ pathname:'/user', state:{day : 'Friday' } })
// 通过下面这个接收到参数
this. props. location. state. day

不建议使用上面这两种传参方式,因为当我们做单页面应用SPA时,这些参数变量,会存储在内存中,页面刷新会丢失。

还是建议使用动态路由传参

this. props. history. push(**/detail/${id}**)

// 通过下面这个接收到参数
this. props. match, params. myid

注意这个myid,是我在根路由中配置的。

# 路由拦截

# withRouter的应用于原理