1 路由跳转模式push与replace
在 React 路由中,有两种常用的路由跳转模式,即 push 和 replace。这两种模式可以通过 React Router 库提供的方法进行实现。
- 默认是push模式。
- Push 模式:
在 push 模式下,路由跳转这会将新的路由添加到浏览器的历史记录中,并在页面上呈现新的路由内容。这样用户可以通过浏览器的后退按钮返回上一个页面。
示例代码参考上一篇文章,这里不在详述。
- Replace 模式:
在 replace 模式下,通过在<Link replace></Link>或者<NavLink replace></NavLink>
或者自定义路由连接组件中添加replace 方法来进行路由跳转。这会替换当前的路由记录,而不会在浏览器的历史记录中创建新的记录。因此,用户无法通过后退按钮返回到之前的页面。
示例代码:
<Link replace to={{pathname: '/home/message/detail', state: msg}}>{msg.title}</Link>
根据具体的需求,选择使用 push 还是 replace 模式。如果希望用户可以通过后退按钮返回到之前的页面,可以使用 push 模式。如果希望在进行路由跳转时替换当前的路由记录,可以使用 replace 模式。
2 编程式导航
2.1 概述
在 React 中,编程式导航是通过使用路由库提供的编程接口来进行页面跳转。React Router 是一个常用的路由库,提供了编程式导航的方法。
以下是在 React 中使用 React Router 实现编程式导航的基本步骤:
- 导入所需的路由库组件和钩子函数:
jsxCopy code
import { useHistory } from 'react-router-dom';
- 在函数组件中获取
history
对象:
jsxCopy code
const history = useHistory();
- 在需要进行页面跳转的事件处理函数中,使用
history
对象进行导航操作。常用的方法包括:
history.push(path)
: 导航到指定的路径,将新的路由添加到浏览器的历史记录中。history.replace(path)
: 导航到指定的路径,替换当前的路由记录,不创建新的历史记录。history.goBack()
: 返回上一个页面,相当于浏览器的后退操作。
示例代码:
jsxCopy code
import { useHistory } from 'react-router-dom';
function MyComponent() {
const history = useHistory();
const handleButtonClick = () => {
// 使用 history.push 进行页面跳转
history.push('/new-route');
};
return (
<div>
<button onClick={handleButtonClick}>Go to New Route</button>
</div>
);
}
通过使用 history
对象提供的方法,可以在事件处理函数中实现编程式导航,从而实现页面的跳转和导航操作。请注意,上述示例中使用了 React Router v6 的 useHistory
钩子函数,如果使用其他版本的 React Router,可能会有稍微的差异。请根据使用的 React Router 版本进行适当的调整。
2.2 示例
在上一篇0604嵌套路由与路由传参-react路由-react示例的基础上,我们在Messge组件中定义三个按键,前进、后退和跳转,通过点击按钮实现相应的功能。
-
改写路由链接
<Link to={`/home/message/detail/${msg.id}/${msg.title}`}>{msg.title}</Link> <button>push 查看</button> <button onClick={() => this.replaceShow(msg.id, msg.title)}>replace 查看</button>
-
replaceShow
/** * 路由跳转replace展示 */ replaceShow = (id, title) => { this.props.history.replace(`/home/message/detail/${id}/${title}`) }
在Message组件中添加三个按钮前进、后退和跳转,实现相应的功能,Message组件jsx代码如下所示:
import React, { Component } from 'react'
import { Link, Route } from 'react-router-dom'
import Detail from './Detail'
export default class Message extends Component {
state = {
messArr : [
{ id: 1, title: '消息1' },
{ id: 2, title: '消息2' },
{ id: 3, title: '消息3' },
]
}
/**
* 路由跳转push展示
*/
pushShow = (id, title) => {
// 接受params参数
this.props.history.push(`/home/message/detail/${id}/${title}`)
// 接受search参数
// this.props.history.push(`/home/message/detail/?id=${id}&title=${title}`)
// 接受state参数
// this.props.history.push(`/home/message/detail`, {id, title})
}
/**
* 路由跳转replace展示
*/
replaceShow = (id, title) => {
// 接受params参数
this.props.history.replace(`/home/message/detail/${id}/${title}`)
// 接受search参数
// this.props.history.replace(`/home/message/detail/?id=${id}&title=${title}`)
// 接受state参数
// this.props.history.replace(`/home/message/detail`, {id, title})
}
/**
* 前进
*/
forward = () => {
this.props.history.goForward()
}
/**
* 后退
*/
back = () => {
this.props.history.goBack()
}
/**
* 跳转
*/
go = () => {
this.props.history.go(-1)
}
render() {
const { messArr } = this.state
return (
<div>
<ul>
{
messArr.map((msg) => {
return (
<li key={msg.id}>
{/* 向路由组件传递params参数 */}
<Link to={`/home/message/detail/${msg.id}/${msg.title}`}>{msg.title}</Link>
<button onClick={() => this.pushShow(msg.id, msg.title)}>push 查看</button>
<button onClick={() => this.replaceShow(msg.id, msg.title)}>replace 查看</button>
{/* 向路由组件传递search参数 */}
{/* <Link to={`/home/message/detail/?id=${msg.id}&title=${msg.title}`}>{msg.title}</Link> */}
{/* 向路由组件传递state参数 */}
{/* <Link replace to={{pathname: '/home/message/detail', state: msg}}>{msg.title}</Link> */}
{/* <Link to={{pathname: '/home/message/detail', state: msg}}>{msg.title}</Link> */}
</li>
)
})
}
</ul>
<hr />
{/* 声明接收params参数 */}
<Route path="/home/message/detail/:id/:title" component={Detail}></Route>
{/* search参数无需声明接收 */}
{/* state参数无需声明接收 */}
{/* <Route path="/home/message/detail" component={Detail}></Route> */}
<button onClick={this.forward}>前进</button>
<button onClick={this.back}>后退</button>
<button onClick={this.go}>跳转</button>
</div>
)
}
}
2.3 总结
借助this.props.history对象上的API实现路由的跳转、前进、后退等功能
- push():路由跳转push模式
- replace():路由跳转replace模式
- goBack():路由导航后退
- goForward():路由导航前进
- go():根据参数大小决定是前进还是后退以及跳转几步
3 withRouter
路由组件可以通过this.props.history提供的API实现路由功能,那么如果是普通的组件怎么实现呢?
需要通过引入withRouter方法来实现,示例如下。
以#2中示例为基础,其中Header组件为一般组件,添加三个按钮:前进、后退及跳转,通过点击不同的按钮实现对应的功能。
import React, { Component } from 'react'
import { withRouter } from "react-router-dom";
class Header extends Component {
/**
* 前进
*/
forward = () => {
this.props.history.goForward()
}
/**
* 后退
*/
back = () => {
this.props.history.goBack()
}
/**
* 跳转
*/
go = () => {
this.props.history.go(-1)
}
render() {
// console.log('Header组件收到的props:', this.props);
return (
<div className="page-header">
<h2>React Router Demo</h2>
<button onClick={this.forward}>前进</button>
<button onClick={this.back}>后退</button>
<button onClick={this.go}>跳转</button>
</div>
)
}
}
export default withRouter(Header)
注意:在导出的时候是导出withRouter(组件)函数返回的结果
4 BrwoserRouter与HashRouter的区别
- 底层原理不同
- BrowserRouter使用的是H5 的history API,不兼容IE9及一下版本
- HashRouter使用的是URL的哈希值
- url表现形式不一样
- BrowserRouter路径中没有#,示例:
http://127.0.0.1/demo/test
- HashRouter路径中带#,示例:
http://127.0.0.1/#/demo/test
- BrowserRouter路径中没有#,示例:
- 刷新后对路由state参数影响
- BrowserRouterf没有影响,因为state保存在history中
- HashRouter刷新后会导致state参数丢失
- 备注:HashRouter可以解决一些路径错误相关的问题。
结语
❓QQ:806797785
⭐️源代码仓库地址:https://github.com/gaogzhen/react-staging.git
参考:
[1]React视频教程[CP/OL].2020-12-15.p90-93.
[2]React官网[CP/OL].