文章目录
- 1. 相关理解
- 1.1. SPA的理解
- 1.2. 路由的理解
- 1.2.1 什么是路由?
- 1.2.2 路由分类
- 2. react-router-dom相关API
- 2.1. 内置组件
- 2.2. 其它
- 3. 基本路由使用
- 3.1. 效果
- 3.2. 准备
- 3.3 路由的基本使用
- 3.4 实现
- 3.5 路由组件与一般组件的区别
- 3.6 NavLink与封装NavLink
- 3.7 Switch的使用
- 3.8 解决多级路径刷新页面样式丢失的问题
- 3.9 路由的严格匹配与模糊匹配
- 3.10 Redirect的使用 【重定向】
- 4. 嵌套路由使用
- 4.1 效果
- 4.2 注意
- 4.3 实现
- 5. 向路由组件传递参数数据
- 5.1 效果
- 5.2 具体方法
- 方法1. params参数
- 方法2. search参数
- 方法3. state参数
- 代码
- 6. 多种路由跳转方式
- 6.1 push与replace模式
- 6.2 编程式路由导航
- 6.3 withRouter的使用
- 7. 注意
- BrowserRouter与HashRouter的区别
1. 相关理解
1.1. SPA的理解
单页Web应用(single page web application,SPA)
整个应用只有一个完整的页面。
点击页面中的链接不会刷新页面,只会做页面的局部更新。
数据都需要通过ajax请求获取, 并在前端异步展现。
1.2. 路由的理解
1.2.1 什么是路由?
一个路由就是一个映射关系(key: value)
key为路径, value可能是function或component
1.2.2 路由分类
1. 后端路由
理解: value是function, 用来处理客户端提交的请求。
注册路由:router.get(path, function(req, res))
工作过程:当node接收到一个请求时, 根据请求路径找到匹配的路由, 调用路由中的函数来处理请求, 返回响应数据
![在这里插入图片描述 [react] 路由_SPA](https://file.cfanz.cn/uploads/png/2022/12/21/13/07KHb1X13S.png)
2. 前端路由
浏览器端路由,value是component,用于展示页面内容。
注册路由: <Route path="/test" component={Test}> 工作过程:当浏览器的path变为/test时, 当前路由组件就会变为Test组件
路由原理history
![在这里插入图片描述 [react] 路由_API_02](https://file.cfanz.cn/uploads/png/2022/12/21/13/1ce919F86E.png)
![在这里插入图片描述 [react] 路由_react.js_03](https://file.cfanz.cn/uploads/png/2022/12/21/13/9X88cMc7D8.png)
![在这里插入图片描述 [react] 路由_react.js_04](https://file.cfanz.cn/uploads/png/2022/12/21/13/YE2Vb17c0U.png)
![在这里插入图片描述 [react] 路由_API_05](https://file.cfanz.cn/uploads/png/2022/12/21/13/VbY1CD0RAH.png)
2. react-router-dom相关API
2.1. 内置组件
<BrowserRouter>
<HashRouter>
<Route>
<Redirect>
<Link>
<NavLink>
<Switch>
2.2. 其它
history对象
match对象
withRouter函数
3. 基本路由使用
3.1. 效果
![在这里插入图片描述 [react] 路由_react.js_06](https://file.cfanz.cn/uploads/png/2022/12/21/13/KF966396WC.png)
3.2. 准备
下载react-router-dom:
npm install react-router-dom
引入bootstrap.css:
<link rel="stylesheet" href="/css/bootstrap.css">
3.3 路由的基本使用
- 明确好界面中的导航区、展示区
- 导航区的a标签改为Link标签
<Link to="/xxxxx">Demo</Link> - 展示区写Route标签进行路径的匹配
<Route path='/xxxx' component={Demo}/> -
<App>的最外侧包裹了一个<BrowserRouter>或<HashRouter>
3.4 实现
![在这里插入图片描述 [react] 路由_react.js_07](https://file.cfanz.cn/uploads/png/2022/12/21/13/J844126394.png)
![在这里插入图片描述 [react] 路由_API_08](https://file.cfanz.cn/uploads/png/2022/12/21/13/F61T6R40Ae.png)
![在这里插入图片描述 [react] 路由_Test_09](https://file.cfanz.cn/uploads/png/2022/12/21/13/3PEK6G2HW4.png)
![在这里插入图片描述 [react] 路由_SPA_10](https://file.cfanz.cn/uploads/png/2022/12/21/13/HbL6GA9Cdd.png)
![在这里插入图片描述 [react] 路由_react.js_11](https://file.cfanz.cn/uploads/png/2022/12/21/13/4S4Q89174I.png)
![在这里插入图片描述 [react] 路由_API_12](https://file.cfanz.cn/uploads/png/2022/12/21/13/D37UEJ7577.png)
3.5 路由组件与一般组件的区别
写法不同:
一般组件:<Demo/> 路由组件:<Route path="/demo" component={Demo}/> 存放位置不同:
一般组件:components 路由组件:pages 接收到的props不同:
一般组件:写组件标签时传递了什么,就能收到什么
路由组件:接收到三个固定的属性
history:
go: ƒ go(n)
goBack: ƒ goBack()
goForward: ƒ goForward()
push: ƒ push(path, state)
replace: ƒ replace(path, state)
location:
pathname: "/about"
search: ""
state: undefined
match:
params: {}
path: "/about"
url: "/about"
3.6 NavLink与封装NavLink
NavLink可以实现路由链接的高亮,通过activeClassName属性指定样式名,默认是"active"
<NavLink activeClassName="demo" className="list-group-item" to="/home">Home</NavLink>
可以自己封装一个NavLink【一般组件】
标签体内容是特殊的标签属性,通过this.props.children可以获取标签体内容
import React, { Component } from 'react'
import {NavLink} from 'react-router-dom'
export default class MyNavLink extends Component {
render() {
// console.log(this.props);
return (
<NavLik activeClassName="demo" className="list-group-item" {...this.props} />
)
}
}![在这里插入图片描述 [react] 路由_Test_13](https://file.cfanz.cn/uploads/png/2022/12/21/13/N65Y8BXbSW.png)
this.props等于{to:’/about’,a:1,b:2,c:3,children:“About”}
![在这里插入图片描述 [react] 路由_react.js_14](https://file.cfanz.cn/uploads/png/2022/12/21/13/Lb16I2116M.png)
![在这里插入图片描述 [react] 路由_SPA_15](https://file.cfanz.cn/uploads/png/2022/12/21/13/9cD51Ma47M.png)
![在这里插入图片描述 [react] 路由_react.js_16](https://file.cfanz.cn/uploads/png/2022/12/21/13/20VHDH99U8.png)
3.7 Switch的使用
通常情况下,path和component是一一对应的关系。
Switch可以提高路由匹配效率(单一匹配)。
<Switch>
<Route path="/about" component={About}/>
<Route path="/home" component={Home}/>
<Route path="/home" component={Test}/>
</Switch>
这样只要匹配到了第一个就不会再往下匹配了
3.8 解决多级路径刷新页面样式丢失的问题
-
public/index.html 中 引入样式时不写./ 写/(常用)【绝对路径】
![在这里插入图片描述 [react] 路由_SPA_17](https://file.cfanz.cn/uploads/png/2022/12/21/13/Ya8B618U74.png)
2. public/index.html 中 引入样式时不写./写 %PUBLIC_URL%(常用)
![在这里插入图片描述 [react] 路由_API_18](https://file.cfanz.cn/uploads/png/2022/12/21/13/F062Z68f0b.png)
3. 使用HashRouter
![在这里插入图片描述 [react] 路由_react.js_19](https://file.cfanz.cn/uploads/png/2022/12/21/13/7f4KZJ4O91.png)
3.9 路由的严格匹配与模糊匹配
- 默认使用的是模糊匹配(简单记:【输入的路径】必须包含要【匹配的路径】,且顺序要一致)
- 开启严格匹配:
<Route exact={true} path="/about" component={About}/> - 严格匹配不要随便开启,需要再开,有些时候开启会导致无法继续匹配二级路由
![在这里插入图片描述 [react] 路由_react.js_20](https://file.cfanz.cn/uploads/png/2022/12/21/13/BJVF28Hf4W.png)
![在这里插入图片描述 [react] 路由_SPA_21](https://file.cfanz.cn/uploads/png/2022/12/21/13/Vb5Z1M7191.png)
3.10 Redirect的使用 【重定向】
- 一般写在所有路由注册的最下方,当所有路由都无法匹配时,跳转到Redirect指定的路由
- 具体编码:
<Switch>
<Route path="/about" component={About}/>
<Route path="/home" component={Home}/>
<Redirect to="/about"/>
</Switch>
4. 嵌套路由使用
4.1 效果
![在这里插入图片描述 [react] 路由_react.js_22](https://file.cfanz.cn/uploads/png/2022/12/21/13/YUYb1eLB6X.png)
![在这里插入图片描述 [react] 路由_Test_23](https://file.cfanz.cn/uploads/png/2022/12/21/13/0b0J162K23.png)
4.2 注意
- 注册子路由时要写上父路由的path值
- 路由的匹配是按照注册路由的顺序进行的
4.3 实现
![在这里插入图片描述 [react] 路由_API_24](https://file.cfanz.cn/uploads/png/2022/12/21/13/7b7468bEdC.png)
src\index.js
![在这里插入图片描述 [react] 路由_Test_25](https://file.cfanz.cn/uploads/png/2022/12/21/13/Fb22A118B0.png)
APP.js
![在这里插入图片描述 [react] 路由_SPA_26](https://file.cfanz.cn/uploads/png/2022/12/21/13/9a737M0Q0Y.png)
src\components\MyNavLink\index.jsx
![在这里插入图片描述 [react] 路由_react.js_27](https://file.cfanz.cn/uploads/png/2022/12/21/13/2TS4666K26.png)
src\pages\About\index.jsx
![在这里插入图片描述 [react] 路由_SPA_28](https://file.cfanz.cn/uploads/png/2022/12/21/13/96K1657I6H.png)
src\pages\Home\index.jsx
![在这里插入图片描述 [react] 路由_Test_29](https://file.cfanz.cn/uploads/png/2022/12/21/13/1f5Q7545X6.png)
src\pages\Home\News\index.jsx
![在这里插入图片描述 [react] 路由_react.js_30](https://file.cfanz.cn/uploads/png/2022/12/21/13/bb4QY4ZL7E.png)
src\pages\Home\Message\index.jsx
![在这里插入图片描述 [react] 路由_react.js_31](https://file.cfanz.cn/uploads/png/2022/12/21/13/I502L2737A.png)
![在这里插入图片描述 [react] 路由_react.js_32](https://file.cfanz.cn/uploads/png/2022/12/21/13/d023LFTFfD.png)
![在这里插入图片描述 [react] 路由_API_33](https://file.cfanz.cn/uploads/png/2022/12/21/13/N4ZB97ACbT.png)
5. 向路由组件传递参数数据
5.1 效果
![在这里插入图片描述 [react] 路由_react.js_34](https://file.cfanz.cn/uploads/gif/2022/12/21/13/2Y725d1766.gif)
![在这里插入图片描述 [react] 路由_Test_35](https://file.cfanz.cn/uploads/png/2022/12/21/13/21WK5c27cK.png)
5.2 具体方法
方法1. params参数
- 路由链接(携带参数):
<Link to='/demo/test/tom/18'}>详情</Link> - 注册路由(声明接收):
<Route path="/demo/test/:name/:age" component={Test}/> - 接收参数:
this.props.match.params
![在这里插入图片描述 [react] 路由_Test_36](https://file.cfanz.cn/uploads/png/2022/12/21/13/7W5069cb3G.png)
![在这里插入图片描述 [react] 路由_API_37](https://file.cfanz.cn/uploads/png/2022/12/21/13/677Ed7DCaI.png)
src/index.js
![在这里插入图片描述 [react] 路由_SPA_38](https://file.cfanz.cn/uploads/png/2022/12/21/13/333f06Rf3X.png)
src/App.jsx
![在这里插入图片描述 [react] 路由_API_39](https://file.cfanz.cn/uploads/png/2022/12/21/13/9I9P9d976W.png)
src\pages\Home\index.jsx
![在这里插入图片描述 [react] 路由_Test_40](https://file.cfanz.cn/uploads/png/2022/12/21/13/407Y61A6SJ.png)
src\pages\Home\Message\index.jsx
![在这里插入图片描述 [react] 路由_react.js_41](https://file.cfanz.cn/uploads/png/2022/12/21/13/8c8XPf5edC.png)
src\pages\Home\Message\Detail\index.jsx
![在这里插入图片描述 [react] 路由_react.js_42](https://file.cfanz.cn/uploads/png/2022/12/21/13/72eCO5B766.png)
![在这里插入图片描述 [react] 路由_API_43](https://file.cfanz.cn/uploads/png/2022/12/21/13/RZ366BX5cN.png)
方法2. search参数
- 路由链接(携带参数):
<Link to='/demo/test?name=tom&age=18'}>详情</Link> - 注册路由(无需声明,正常注册即可):
<Route path="/demo/test" component={Test}/> - 接收参数:
this.props.location.search
备注:获取到的search是urlencoded编码字符串,需要借助querystring解析
![在这里插入图片描述 [react] 路由_API_44](https://file.cfanz.cn/uploads/png/2022/12/21/13/e3AVKaKW56.png)
![在这里插入图片描述 [react] 路由_Test_45](https://file.cfanz.cn/uploads/png/2022/12/21/13/0eI64aQBO1.png)
![在这里插入图片描述 [react] 路由_API_46](https://file.cfanz.cn/uploads/png/2022/12/21/13/YcF6E1K123.png)
![在这里插入图片描述 [react] 路由_SPA_47](https://file.cfanz.cn/uploads/png/2022/12/21/13/8Q0b417XbY.png)
import qs from 'querystring'
let obj = {name:'tom', age:18}
console.log(qs.stringify(obj)) // name=tom&age=18
let str = 'carName=Benz&price=199'
console.log(qs.parse(str)) // {carName: 'Benz', price: 199}
方法3. state参数
- 路由链接(携带参数):
<Link to={{ pathname:'/demo/test', state:{name:'tom',age:18} }}>详情</Link>- 注册路由(无需声明,正常注册即可):
<Route path="/demo/test" component={Test}/> - 接收参数:
this.props.location.state 备注:刷新也可以保留住参数【history对象记录着在】
![在这里插入图片描述 [react] 路由_API_48](https://file.cfanz.cn/uploads/png/2022/12/21/13/1f56QeP6L8.png)
![在这里插入图片描述 [react] 路由_react.js_49](https://file.cfanz.cn/uploads/png/2022/12/21/13/1S64fYS9eQ.png)
![在这里插入图片描述 [react] 路由_API_50](https://file.cfanz.cn/uploads/png/2022/12/21/13/8G56007VS4.png)
![在这里插入图片描述 [react] 路由_react.js_51](https://file.cfanz.cn/uploads/png/2022/12/21/13/ecb7G4625O.png)
代码
Message/index.jsx
export default class Message extends Component {
render() {
const {messageArr} = this.state
return (
<div>
<ul>
{
messageArr.map((msgObj)=>{
return (
<li key={msgObj.id}>
{/* 向路由组件传递params参数 */}
{/* <Link to={`/home/message/detail/${msgObj.id}/${msgObj.title}`}>{msgObj.title}</Link> */}
{/* 向路由组件传递search参数 */}
{/* <Link to={`/home/message/detail/?id=${msgObj.id}&title=${msgObj.title}`}>{msgObj.title}</Link> */}
{/* 向路由组件传递state参数 */}
<Link to={{pathname:'/home/message/detail',state:{id:msgObj.id,title:msgObj.title}}}>{msgObj.title}</Link>
</li>
)
})
}
</ul>
<hr/>
{/* 声明接收params参数 */}
{/* <Route path="/home/message/detail/:id/:title" component={Detail}/> */}
{/* search参数无需声明接收,正常注册路由即可 */}
{/* <Route path="/home/message/detail" component={Detail}/> */}
{/* state参数无需声明接收,正常注册路由即可 */}
<Route path="/home/message/detail" component={Detail}/>
</div>
)
}
}Detail/index.jsx
import React, { Component } from 'react'
// import qs from 'querystring'
export default class Detail extends Component {
render() {
console.log(this.props);
// 接收params参数
// const {id,title} = this.props.match.params
// 接收search参数
// const {search} = this.props.location
// const {id,title} = qs.parse(search.slice(1))
// 接收state参数
const {id,title} = this.props.location.state || {}
const findResult = DetailData.find((detailObj)=>{
return detailObj.id === id
}) || {}
return (
<ul>
<li>ID:{id}</li>
<li>TITLE:{title}</li>
<li>CONTENT:{findResult.content}</li>
</ul>
)
}
}6. 多种路由跳转方式
6.1 push与replace模式
默认就是Pushs模式
开启repalce模式
![在这里插入图片描述 [react] 路由_SPA_52](https://file.cfanz.cn/uploads/png/2022/12/21/13/1f4bE78516.png)
6.2 编程式路由导航
借助this.prosp.history对象上的API对操作路由跳转、前进、后退
-
this.prosp.history.push() -
this.prosp.history.replace() -
this.prosp.history.goBack() -
this.prosp.history.goForward() -
this.prosp.history.go()
![在这里插入图片描述 [react] 路由_API_53](https://file.cfanz.cn/uploads/png/2022/12/21/13/688454QV3H.png)
![在这里插入图片描述 [react] 路由_API_54](https://file.cfanz.cn/uploads/png/2022/12/21/13/Ib2a3157d1.png)
![在这里插入图片描述 [react] 路由_react.js_55](https://file.cfanz.cn/uploads/png/2022/12/21/13/a08T329FI5.png)
6.3 withRouter的使用
export default withRouter(Header)
withRouter可以加工一般组件,让一般组件具备路由组件所特有的API
withRouter的返回值是一个新组件
![在这里插入图片描述 [react] 路由_SPA_56](https://file.cfanz.cn/uploads/png/2022/12/21/13/7fZ6Ff8XA4.png)
![在这里插入图片描述 [react] 路由_API_57](https://file.cfanz.cn/uploads/png/2022/12/21/13/8024Q50R7a.png)
![在这里插入图片描述 [react] 路由_react.js_58](https://file.cfanz.cn/uploads/png/2022/12/21/13/4B611dJ00F.png)
7. 注意
BrowserRouter与HashRouter的区别
- 底层原理不一样:
BrowserRouter使用的是H5的history API,不兼容IE9及以下版本。
HashRouter使用的是URL的哈希值。 -
path表现形式不一样
BrowserRouter的路径中没有#,例如:localhost:3000/demo/testHashRouter的路径包含#,例如:localhost:3000/#/demo/test - 刷新后对路由
state参数的影响
(1) BrowserRouter没有任何影响,因为state保存在history对象中。
(2)HashRouter刷新后会导致路由state参数的丢失!!! - 备注:
HashRouter可以用于解决一些路径错误相关的问题。
![在这里插入图片描述 [react] 路由_react.js_59](https://file.cfanz.cn/uploads/png/2022/12/21/13/QJcFdSQ291.png)
![在这里插入图片描述 [react] 路由_react.js_60](https://file.cfanz.cn/uploads/png/2022/12/21/13/X71G6BccXM.png)
参考:
【React】SPA - 路由机制 - react-router-dom - 基本路由 - 嵌套路由 - 传递参数 - 路由跳转










