【实战】1096- React 中后台系统多页签实现

article/2025/11/4 18:50:49

在中后台管理类系统中,多页签的需求非常普遍,用户常常需要在多个页签内跳转,比如填写表单时去查询某个列表获取一些字段信息再回到表单页面填写。这样的需求在 Vue 中使用 keep-alive 即可实现,但是在 React 中,React Router 切换路由后就会卸载组件,而本身并没有提供类似 keep-alive 的功能,所以实现多页签的功能就会变得格外困难。我的项目也遇到了同样的问题,在 2019 年左右做了技术调研和选型,最终选择了 react-router-cache-route,并在此基础上实现了多页签的需求,并稳定运行了 2 年的时间。下面我来复盘一下这次的多页签改造。

一、项目简介

本项目是我现在所在部门的项目,是一个企业级中后台管理系统,包括系统管理、角色权限体系、基于 Activiti 的工作流引擎等很多开箱即用的功能。项目包括前后端,后端是我们部门自研的基于 Spring 的企业级 Java 框架,前端是 React 技术栈,当时还是 v15 版本。React Router 还是 v2 版本

项目主要对象是提供给科技部门有中后台和流程需求的项目组,基于我们项目提供的基线工程,可以快速搭建工程,在此基础上根据需求进行开发。截止到 2019 年 10 月我离开该项目组,本项目已经服务了行内近 50 个系统。

二、需求背景

当时的多页签需求还是比较明确的,因为我们团队在 2013 年使用 Sea.js + JQuery 的后管类系统都早已实现了,而新的使用 React 技术栈构建的新 UI 却丢失了这个功能,备受用户诟病,期望多页签的需求十分强烈。而 Vue 使用 keep-alive 即可实现多页签功能,如下图的  vue-element-admin  就是典型的多页签案例。

b8c001eb01d6830ad75b9f1182f3039d.png
Vue Element Admin 系统多页签实现

React 多页签本身好实现,难点是没有官方提供类似 Vue 的 keep-alive 功能,而使用 React Router,路由切换会直接卸载组件,导致无法缓存,用户的数据和行为因此丢失了。

社区上关于多页签的需求呼声也非常高,但是如 React 社区比较出名的中后台方案 Ant Design Pro 也不支持该功能,两年没看,至今仍然有很多 Issue 提出这类需求:

559c71ad28e7ec04c3adb26cb658ecf8.png
Antd Pro 社区多页签需求 Issues

偏右大佬早在 2017 年对此做出了回应,详见“能否提供tab切换模式 · Issue #220 · ant-design/ant-design-pro · GitHub”,这个 Isuue 虽然关闭了,但这些年仍然活跃:

abd0b92851b7cf1d5fdf1fb3445f035f.png
偏右 2017 年的回应

看 👎 的数量就知道,用户其实对这种回答很不买帐。再来看 2019 年偏右对这个问题的解释,稍微具体了些:

e975af29be93b22ace1ea47757205494.png
偏右 2019 年的回应

这个解释我个人并不完全认同。首先说 “tab 模式无法(不适合)进行 url 的分享”其实是不成立的, url 带路由和参数就能准确跳转到对应页面,这在我们系统和 Vue 的多页签系统里都是基本功能;而说浏览器本身有 tabs 就不需要做到网站内部,也比较片面,SPA 的页面不开浏览器 tab 应该更符合 Antd 的设计价值观:足不出户 - Ant Design,就连最新版的 Chrome 都已经支持“群组”功能了,让用户在 SPA 页面尽量不开浏览器页签才应该是更好的体验设计。

看看社区其他人的理性分析:

a41049fdcf7cf7c558be3865e558fe05.png
社区用户反馈

三、方案选型

经过一番调研之后,基本的思路大概有三种:

  1. 使用 Redux,数据往 store 里面怼,实现页面数据的”缓存“。

  2. 改写 React Router 源码,切换路由不卸载,改为隐藏。

  3. 使用社区的轮子,当时选了GitHub 里的两个产品:React Keeper  和 react-router-cache-route

其实每种方案都存在一些问题,最终的选择是使用了排除法。第一种方案的缺点是,由于存在大量的存量项目,而且项目本身的代码也很多,改造侵入性比较大,不是很好的选择。第二种的思路和  react-router-cache-route  比较像,就不想重复造轮子了。第三种选用开源方案其实当时也不太想选择,别看现在这两个项目都有 700 多 star,在当时 star 数只有几十个而且 Issue 和 Pr 也很少,也就是用户和贡献者都不多,所以担心会有后续维护性的问题以及隐藏的暗坑。

最终同事选择了 react-router-cache-route,但在当时在项目尝试集成的时候,直接就报个错,给了我同事当头一棒,详见这个 Issue。

335f8332f3976ec84ac3bb1c4c30e57a.png


同事找到我来排查问题,经过定位,发现是 React 16 的一个 Breaking Change 导致的,从 React 16 版本开始, React 组件可以返回数组了,而 React 15 不行,详见我提交的这个 PR。
fcf2fb021959511c7c3c43cd51ffe460.png

解决了 react-router-cache-route 在 React 15 版本报错问题之后,接下来的工作就是实现页签的 UI 和打开关闭的逻辑了,注意关闭需要调用  react-router-cache-route 的卸载缓存 API。

四、还存在什么问题

项目组深度使用  react-router-cache-route  两年时间了,期间由于 React 和 React Router 版本迭代也出现过一些问题,好在  react-router-cache-route 的作者一直保持更新,解决了很多棘手的问题。

但目前总结起来仍然存在两个问题,一个是嵌套的 Cache Route 内部 Route 无法清除缓存问题,刚才看了一下,这个问题终于有了解,详见 Issue #64 :

40b7e99424fbb2a482d87ab1b4d138c8.png
嵌套路由无法清楚缓存问题时隔一年才有解法

但这个问题大约 1 年时间才有解!

还有一个问题,这个其实不是 react-router-cache-route 的问题。我们在多页签的迭代中增加了相同组件多开功能,这个场景比较常见,比如列表页点击链接跳转到表单页,可以同时打开多个表单,这样在不使用 Redux 是没有什么问题,但是一旦数据存在 Redux 中,多开组件就会有问题,显示的始终是 store 中最新的数据,要解决这个问题,需要重构 Redux 相关逻辑,比较麻烦。

五、现在 React 多页签方案有啥新进展吗

有很长时间没关注了,这两天复盘看了看相关 Issue,发现又出现了一些新的轮子,没有验证过,先放在下面供同学们参考。如果想要实现多页签功能的同学,还是推荐使用 react-router-cache-route,毕竟我们已经稳定使用两年多了,没有太大问题。

  • react-router-cache-route (推荐)

  • React Activation (和上面的工具同一个作者,Vue 中功能在 React 中的实现,配合 babel 预编译实现更稳定的 KeepAlive 功能)

  • umi-plugin-keep-alive (上面轮子的 umi 插件)

  • react-keeper (774 star)

  • react-antd-multi-tabs-admin (73 star,Antd多标签页后台管理模板)

  • react-live-route (207 star,也是一种缓存路由的轮子)

  • React Ant (232 star,基于Ant Design Pro 2.0 的多标签页tabs)

  • Ant Design Pro Plus ( 88 star,基于 ant-design-pro 做一些微小的工作)

  • React Admin (83 star,基于 Ant Design React 的管理系统架构)

  • ant_pro_tabs (82 star,基于 Ant Design Pro 4 实现多标签页面,包括:路由联动,列表,多详情页共存,自动新增、关闭标签等功能)

  • Antd Pro Page Tabs ( 54 star,Ant Design Pro 多页签,基于 UmiJS )

  • alita/packages/tabs-layout(基于 umi 的移动端 react 框架的缓存插件)

大家选择的时候可以考察其原理,star 数,Issue 数,PR 数等,当然,也可以看看他们实现的原理,学习一下这块的思路也是不错的。

六、结语

中后台类系统多页签的需求应该是很多的,React 技术栈目前还没有大一统的解决方案,目前是轮子齐飞的状态。希望本文的经验能够帮助到大家,少走弯路。

b679a6423da1a9b719770186d1a4a809.gif

1. JavaScript 重温系列(22篇全)

2. ECMAScript 重温系列(10篇全)

3. JavaScript设计模式 重温系列(9篇全)

4. 正则 / 框架 / 算法等 重温系列(16篇全)

5. Webpack4 入门(上)|| Webpack4 入门(下)

6. MobX 入门(上) ||  MobX 入门(下)

7. 120+篇原创系列汇总

2ecbabddd73942399edc848c61183f4f.gif

回复“加群”与大佬们一起交流学习~

点击“阅读原文”查看 120+ 篇原创文章


http://chatgpt.dhexx.cn/article/6t12Gk8s.shtml

相关文章

多种方式带你玩转 javascript 实现关闭浏览器页签

你知道的越多,你不知道的越多 点赞再看,养成习惯 如果您有疑问或者见解,或者没有积分想获取项目,欢迎指教: 企鹅:869192208 文章目录 前言方法一方法二方法三方法四方法五方法六附录 前言 近日&#xff0c…

vue 后台系统中多页面标签

在后台开发中,常用一种页面标签工具,每次点击菜单栏时,会在页面区域上方增加一个【标签页】如下图,可关闭,可切换页面等功能,常见于后台管理系统中。 以前,我以为这个是利用tabs组件开发的&…

js关闭浏览器页签

兼容性 js实现 function closeWebPage(){if (navigator.userAgent.indexOf("MSIE") > 0) {if (navigator.userAgent.indexOf("MSIE 6.0") > 0) {window.opener null;window.close();}else {window.open(, _top);window.top.close();}}else if (nav…

layui————一个页面展示两个页签

html页面 <!DOCTYPE html> <html> <head><meta charset"utf-8"><link rel"stylesheet" href"../../../build/css/base.css" media"all"> </head> <body> <div class"layui-tab la…

SAP BP屏幕增强页签

导语&#xff1a;最近收到了BP的需求&#xff0c;要增加页签&#xff0c;找了一些资料&#xff0c;发现BP的增强页签可是真麻烦啊&#xff0c;下面把我梳理出来的分享一下。 &#x1f449;【增强记录清单…】 需求&#xff1a; 需求是在供应商界面增加一个页签&#xff0c;用…

修改浏览器页签名称

第一种若是整个系统要统一修改为一个名称 在public文件夹下index.html下直接修改或者在相应配置文件package.json或者其他&#xff08;看项目配置&#xff09; 第二种某一个路由或者菜单页签不一样的名称 可以配置到后置路由中或者组件内 语句为:document.title 测试

vue实现tagsview多页签导航功能

文章目录 前言一、效果图二、实现思路1. 新建 tags-view.js2. 在Vuex里面引入 tags-view.js3. 新建 tabsView 组件4. 新建 ScrollPane 组件5. 引入 tabsView 组件6. 使用 keep-alive 组件&#xff0c;进行页签的缓存 总结 前言 基本上后台管理系统都需要有多页签的功能&#x…

基于微前端qiankun的多页签缓存方案实践

作者&#xff1a;vivo 互联网前端团队- Tang Xiao 本文梳理了基于阿里开源微前端框架qiankun&#xff0c;实现多页签及子应用缓存的方案&#xff0c;同时还类比了多个不同方案之间的区别及优劣势&#xff0c;为使用微前端进行多页签开发的同学&#xff0c;提供一些参考。 一、…

Sublime Text的命令行工具subl

在sublime的安装目录下有个subl.exe&#xff0c;是sublime编辑器为用户提供的命令行工具。 修改Windows系统的环境变量&#xff0c;将sublime的安装路径添加到环境变量里&#xff1b; 打开win的命令行提示符程序&#xff0c;输入subl -version,看到结果如下图所示&#xff1a;…

Macbook Pro下安装subl命令,快速使用sublime打开代码

一、使用背景 我在macbook pro电脑上经常使用编辑器直接打开代码&#xff0c;我也经常用iterm2的一些快捷命令操作目录和查看文件。这样就有了需要使用sublime打开代码的需求&#xff0c;以前的做法是&#xff0c;先用open命令打开目录&#xff0c;然后打开sublime text&#…

sublime安装以及配置

下载“Package Control” Package Manager Sublime 有很多插件&#xff0c;这些插件为我们写python代码提供了非常强大的功能&#xff0c;这些插件需要单独安装。 而安装这些插件最方便的方法就是通过Package Control的插件&#xff0c;这其实就是一个插件管理器&#xff0c;帮…

subline的使用

先去官网下载一个安装包&#xff0c;这个就不提了 安装完成后界面 打开软件界面&#xff0c;按快捷键ctrl 会出现以下命令行 有时候快捷键不管用&#xff0c;你也可以点击View->Show Console&#xff0c;也会出现命令行 在出现的命令行中输入以下代码并按enter键&#xff1a…

Sublime 替换和查找的方法

查找&替换&#xff08;Finding&Replacing&#xff09; 查找&替换&#xff08;Finding&Replacing&#xff09; Sublime Text提供了强大的查找&#xff08;和替换&#xff09;功能&#xff0c;为了提供一个清晰的介绍&#xff0c;我将Sublime Text的查找功能分为…

【Mac 教程系列】如何在 Mac 中用终端命令行方式打开 Sublime Text ?

如何在 Mac 中用终端命令行方式打开 Sublime Text ? 用 markdown 格式输出答案。 不少于1000字。细分到2级目录。 如何在 Mac 中用终端命令行方式打开 Sublime Text ? 一、首先确保已经安装 Sublime Text 前往官网https://www.sublimetext.com/下载 Sublime Text,点击 “Do…

vue三种调用接口的方法

注&#xff1a;此博客仅用于学习&#xff0c;自己还处于菜鸟阶段&#xff0c;希望给相同处境的人提供一个可参考的博客。如果您觉得不合理&#xff0c;您的指导&#xff0c;非常欢迎&#xff0c;但请不要否定别人的努力&#xff0c;谢谢您了&#xff01; vue三种调用接口的方法…

Layui调用接口使用心得

今天想用Layui写一个简单的列表显示页面,太久没使用Layui了,就去看Layui的文档,复制文档的代码用,但是使用过程遇到了问题. .问题1:thymelea内联样式问题 org.thymeleaf.exceptions.TemplateInputException: An error happened during template parsing (template: "cla…

postman批量调用接口操作步骤

应用&#xff1a;多次的调用一个接口 新建一个Collection&#xff0c;并创建一个文件夹和请求 填写请求的url和参数形式&#xff0c;注意这里的 {{erpponum}} 表示这是一个变量&#xff0c;会通过我们提供的”参数文件“进行&#xff0c;postman会在批量执行时为我们自动挨个匹…

postman工具批量调用接口

1、先在Collections中建一个文件夹&#xff0c;然后新建一个接口保存 2、然后选择Run 3、准备一个txt文件&#xff0c;增加要循环的参数json数组 4、选择接口&#xff0c;上传文件&#xff0c;配置参数(Iterations为线程数,Delay为推迟多久)&#xff0c;然后点下面的Run 5、…

kettle实战之调用接口

从今天开始将本人在工作当中&#xff0c;处理的一些Kettle过程记录下来&#xff0c;供大家参考学习。 在日常数据处理过程中&#xff0c;会涉及调用对方接口获取数据&#xff0c;来向自己的数据库中插入大量业务数据&#xff0c;这里说明一下数据处理过程中&#xff0c;经常会…

Element 调用接口

博主之前已经为大家讲了Element入门教程&#xff0c;如果还有什么疑问的话可以查看博主置顶的文章。相信大家对Element 框架已经有了一个基本的了解&#xff0c;这次为大家讲一下如何调用接口。 以我自己为例子&#xff0c;我想要调用我接口里的图片&#xff0c;并让他在浏览器…