目录
(1)BrowserRouter和HashRouter
(2)Route
(4)Switch
一、路由理解
1.什么是路由
-
一个路由就是一个映射关系(key:value)
-
key为路径, value可能是function或component
2.路由分类
(1)后端路由
- 理解: value是function, 用来处理客户端提交的请求。
-
注册路由: router.get(path, function(req, res))
-
工作过程:当node接收到一个请求时, 根据请求路径找到匹配的路由, 调用路由中的函数来处理请求, 返回响应数据
(2)前端路由
- 浏览器端路由,value是component,用于展示页面内容
-
注册路由: <Route path="/test" component={Test}>
-
工作过程:当浏览器的path变为/test时, 当前路由组件就会变为Test组件
3.react-router-dom的理解
-
react的一个插件库
-
专门用来实现一个SPA应用
-
基于react的项目基本都会用到此库
4.路由组件上的props上面会携带一些相关的api
二、react-router-dom相关API
1.内置组件
(1)<BrowserRouter>和<HashRouter>
BrowserRouter 和 HashRouter 都可以实现前端路由的功能。
用法:对路由进行一个包裹。
import {HashRouter,Route,Link } from 'react-router-dom'
export default class App extends Component {
render() {
return (
<div>
<HashRouter>
{/* 编写路由链接 */}
<Link className="list-group-item" to="/about">
About
</Link>
<Link className="list-group-item" to="/home">
Home
</Link>
{/* 注册路由 */}
<Route path="/about" component={About} />
<Route path="/home" component={Home} />
<HashRouter/>
</div>
);
}
}
注意点:
如果使用了BrowserRouter组件的话,就有可能引发刷新样式丢失的问题,解决方案:
-
在public/index.html中引入样式时不写./ 写/或者省略不写(常用)
-
在public/index.html中引入样式时不写./ 写%PUBLIC_URL% (常用)
-
使用HashRouter组件
如果使用了HashRouter组件的话,那么就无法使用路由组件上的props.location.state为一个空对象,浏览器端可能会报错。在使用时,可这样写props.location.state||{}
(2)<Route>
Route一般用于注册路由。
例如: <Route path="匹配的路径" component={路由组件名称} />
(3)<Link>和<NavLink>
Link和NavLink功能相差无几,都是编写路由链接。但是NavLink可以指定专属激活样式的类名:
关键字:activeClassName
<NavLink to="/about" activeClassName="active">About</NavLink>
(4)<Switch>
通常情况下,path和component是一一对应的关系。但是点击了Link或NavLink后,拿到的path会在Route全部进行匹配,资源比较浪费。加入了Switch组件后,如过匹配到了,就不会继续往下接着匹配了,优化了效率问题。
用法:
<Switch>
<Route path="/about" component={About} />
<Route path="/home" component={Home} />
<Route path="/home" component={Text} />
</Switch>
(5)<Redirect>(路由重定向)
案例:
<Switch>
<Route path="/about" component={About} />
<Route path="/home" component={Home} />
<Route path="/home" component={Text} />
{/* 路由重定向 */}
<Redirect to="/about" />
</Switch>
以上内置组件都需要引入后,才能使用。
2.嵌套路由
一级路由:
<MyNavLink to="/about">About</MyNavLink>
<MyNavLink to="/home">Home</MyNavLink>
<Switch>
<Route path="/about" component={About} />
<Route path="/home" component={Home} />
<Route path="/home" component={Text} />
{/* 路由重定向 */}
<Redirect to="/about" />
</Switch>
二级路由:
<MyNavLink to="/home/news">News</MyNavLink>
<MyNavLink to="/home/message">Message</MyNavLink>
<Switch>
<Route path="/home/news" component={News}></Route>
<Route path="/home/message" component={Message}></Route>
<Redirect to="/home/news" />
</Switch>
注意点:
-
注册子路由的时候要写上父路由的path值
-
路由的匹配是按照注册路由的顺序进行的
3.路由传参(三种方式)
(1)params传参
第一步:向组件传递params参数
<Link to={`/home/message/detail/${id}/${title}`}>{message.title}</Link>
第二步:声明接收params参数
<Route path="/home/message/detail/:id/:title" component={Detail} />
第三步:接收params参数
render() {
const {id,title} = this.props.match.params
const content = DetailData.find(obj=>id===obj.id)
return (
<ul>
<li>ID:{id}</li>
<li>标题:{title}</li>
<li>内容:{content.content}</li>
</ul>
)
}
(2)search传参(与query传参相似)
第一步:向组件传递search参数,这种格式的编码叫做urllencode编码格式
<Link to={`/home/message/detail/?id=${.id}&title=${title}`}>{message.title}</Link>
第二步:声明接收search参数 (search参数无需声明接收,正常注册即可)
<Route path="/home/message/detail" component={Detail} />
第三步:接收search参数 (需要用到react脚手架中自带的querystringify库解析这种格式)
// 解析query参数
import qs from 'querystringify'
render() {
const { id, title } = qs.parse(this.props.location.search)
const content = DetailData.find(obj => id === obj.id)
return (
<ul>
<li>ID:{id}</li>
<li>标题:{title}</li>
<li>内容:{content.content}</li>
</ul>
)
}
(2)state传参
第一步:向组件传递state参数(向组件传递state参数,与组件的state无关系)
<Link to={{ pathname: '/home/message/detail', state: { id:id, title:title } }}>{title}</Link>
第二步:声明接收state参数(与search一致,无需声明接收,正常注册即可)
<Route path="/home/message/detail" component={Detail} />
第三步:接收state参数 (加{}可以防止history里面的location.state为undefined报错问题)
render() {
const { id, title } = this.props.location.state || {}
const content = DetailData.find(obj => id === obj.id) || {}
return (
<ul>
<li>ID:{id}</li>
<li>标题:{title}</li>
<li>内容:{content.content}</li>
</ul>
)
}
4.精准匹配与模糊匹配
模糊匹配规则: 只要pathname(link的to属性/地址栏url的pathname)是以<Route>的path属性的值开头,就能匹配成功。
精准匹配与模糊匹配相反。
<Switch>
{/* Route默认是模态匹配,exact开启精准匹配 */}
<Route exact path="/about" component={About} />
<Route path="/home" component={Home} />
<Route path="/home" component={Text} />
</Switch>
5.push模式与replace模式
路由跳转有两种模式push(栈)和replace(替换),默认开启的是push模式。
push模式可以进行前进和后退,relace模式则无法进行前进和后退。
使用replace关键字即可开启replace模式。
<Link replace to={{ pathname:'/home/message/detail',state:{id,title}}}>{title}</Link>
6.编程式路由导航
<button onClick={() => this.showPush(message.id, message.title)}>push查看</button>
<button onClick={() => this.showReplace(message.id, message.title)}>replace查看</button>
<button onClick={this.back}>后退</button>
<button onClick={this.goto}>前进</button>
// replace编程式路由跳转
showReplace = (id, title) => {
// params带参
this.props.history.replace(`/home/message/detail/${id}/${title}`)
}
// push编程式路由跳转
showPush = (id, title) => {
// params接参
this.props.history.push(`/home/message/detail/${id}/${title}`)
}
back = () => {
this.props.history.goBack()
}
goto = () => {
this.props.history.goForward()
}
7.withRouter()的使用
withRouter()方法可以在一个一般组件上添加路由组件的api
用法:
import React, { Component } from 'react'
import { withRouter } from 'react-router-dom'
class Header extends Component {
render() {
return (
<div>
<h2>嘿嘿嘿<h2/>
</div>
)
}
}
export default withRouter(Header)