React-router 将弹框Modal嵌入路由(create a modal route with react-router)
背景:
在使用react-router时,我们往往只有在真实的需要页面跳转时,才会将页面加入路由(Route)。对于弹框(Modal),却总是会忽视它的路由需求。
在开发者眼中: 弹框只是页面中的附属,无需单独准备路由存放。当然,也有其他原因,比如我们想要一个公用的方法,以此来显示弹框。诸如此类,导致开发时没有正视弹框。
可在用户眼中: 弹框也是页面,至少在想要返回的时候,移除弹框即可(不要把弹框下的页面也给返回了)。
因此,Modal弹框、Route路由、BackPress物理返回 三者间的微妙关系就变得尤为关键了
目的:
用户视角: 弹框显示时,物理返回(手机返回操作、浏览器左上角回退按钮),只隐藏弹框(不影响下层页面内容,比如滚动、比如输入框内容)
开发者视角: 1. 原本的目的很简单,只需要在有弹框显示时,物理返回隐藏弹框的同时阻止下层页面的返回
2. 将弹框加入路由,弹框即页面,会被路由同等对待
几次尝试:
1. 使用 popstate 监听
window.addEventListener("popstate", () => {});
2. 使用history.listen监听
history.listen((newLocation, action) => { if(action === "PUSH) { } else { // 判断是否存在弹框 if(ReactDOM.findDOMNode(document.getElementById("modal"))) { // 隐藏弹框
// 前进一个路由 history.go(1) } } })
注意: 以上方法均是通过监听路由变化(popstate监听、history.listen监听),并辅以判断弹框的显示与否来确定。
此处使用的是history.go(1)前进一个路由,因为无法阻止在物理返回时的路由回退,只能通过 回退 - 判断有弹框 - 前进 的流程进行
将Modal加进路由的尝试:
// - Router.js中使用: <BrowserRouter> <Switch> ... </Switch> <Route path="/" component={Login}> </BrowserRouter> // - 显示Modal(跳转Login路由): <Linl to={{pathname: this.props.match.url, search: "?login=true"}}>To Login</Link> // - Login.js中使用 render() { let params = new URLSearchParams(this.props.location.search); return( params.get("login") && (<Modal>...</Modal>) ) }
// - 需要显示Modal的 profile.js <Link to={this.props.match.url + "/modal"}>Show Modal</Link> <Route path={this.props.match.url + "/modal"} render={() => { return ( <Modal onClick={() => this.props.history.goBack()}> ... </Modal> ) }} /> // - Modal.js 内容: render() { return React.createPortal( <div onClick={this.props.onClick}> ... </div> ) }
最终使用的方法
引用:
title: Create a Modal Route with React Router
author: Jason Brown
url: https://codedaily.io/tutorials/77/Create-a-Modal-Route-with-React-Router
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了