# 什么是路由?
路由是根据不同的url地址展示不同的内容或页面。 一个针对React而设计的路由解决方案、可以友好的帮你解决React components 到 URl之间的同步映射关系。
示例网站: react-router示例
# 路由安装
npm install react‐router‐dom
# 路由使用
- 路由导入
- 定义路由及重定向
使用Redirect进行路由重定向匹配,由于是贪婪匹配,在上面例子中,如果已经匹配到了center路由,此时刷新页面会继续匹配到**/**根路由。
所以一般在使用HashRouter时配套使用Switch,匹配到路由之后立马跳出,只能匹配到第一个符合条件的路由。
# HashRouter与BrowserRouter的异同
HashRouter的特点:localhost:3000/#/film
HashRouter在路径中包含了**#,相当于锚点定位,因此不论#**后面的路径怎么变化,请求的都相当于是#之前的那个页面,可以很容易的进行前后端不分离的部署(也就是把前端打包后的文件放到服务器端的public或static里)。
这个警告只有在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、Center,flim路由包括nowplaying,comingsoon路由,我们就把这两个分路由,定义在flim路由组件里。
# 路由跳转方式
- 声明式导航 NavLink根据className判断自带高亮效果
- 编程式导航:通过**this.props.history.push()**跳转路由
如果想要做列表页路由跳转详情页面路由,步骤是:
- 先在列表页nowplaying取得每条信息的id值,
- 在根路由配置 详情页面的的myid
- 根据不同的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)
在后面。我们会详细介绍高阶组件,可以简单理解为 高阶组件为其包裹组件包裹生成了一个干爹组件,把需要的属性,我们传递进来。
# 路由传参
(1)
this. props. history. push({ pathname : '/user' , query : { day: 'Friday'} })
// 通过下面这个接收到参数
this. props. location. query. day
(2)
this. 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,是我在根路由中配置的。