【實(shí)戰(zhàn)】1096- React 中后臺系統(tǒng)多頁簽實(shí)現(xiàn)
在中后臺管理類系統(tǒng)中,多頁簽的需求非常普遍,用戶常常需要在多個頁簽內(nèi)跳轉(zhuǎn),比如填寫表單時去查詢某個列表獲取一些字段信息再回到表單頁面填寫。這樣的需求在 Vue 中使用
keep-alive即可實(shí)現(xiàn),但是在 React 中,React Router 切換路由后就會卸載組件,而本身并沒有提供類似keep-alive的功能,所以實(shí)現(xiàn)多頁簽的功能就會變得格外困難。我的項(xiàng)目也遇到了同樣的問題,在 2019 年左右做了技術(shù)調(diào)研和選型,最終選擇了 react-router-cache-route,并在此基礎(chǔ)上實(shí)現(xiàn)了多頁簽的需求,并穩(wěn)定運(yùn)行了 2 年的時間。下面我來復(fù)盤一下這次的多頁簽改造。
一、項(xiàng)目簡介
本項(xiàng)目是我現(xiàn)在所在部門的項(xiàng)目,是一個企業(yè)級中后臺管理系統(tǒng),包括系統(tǒng)管理、角色權(quán)限體系、基于 Activiti 的工作流引擎等很多開箱即用的功能。項(xiàng)目包括前后端,后端是我們部門自研的基于 Spring 的企業(yè)級 Java 框架,前端是 React 技術(shù)棧,當(dāng)時還是 v15 版本。React Router 還是 v2 版本。
項(xiàng)目主要對象是提供給科技部門有中后臺和流程需求的項(xiàng)目組,基于我們項(xiàng)目提供的基線工程,可以快速搭建工程,在此基礎(chǔ)上根據(jù)需求進(jìn)行開發(fā)。截止到 2019 年 10 月我離開該項(xiàng)目組,本項(xiàng)目已經(jīng)服務(wù)了行內(nèi)近 50 個系統(tǒng)。
二、需求背景
當(dāng)時的多頁簽需求還是比較明確的,因?yàn)槲覀儓F(tuán)隊(duì)在 2013 年使用 Sea.js + JQuery 的后管類系統(tǒng)都早已實(shí)現(xiàn)了,而新的使用 React 技術(shù)棧構(gòu)建的新 UI 卻丟失了這個功能,備受用戶詬病,期望多頁簽的需求十分強(qiáng)烈。而 Vue 使用 keep-alive 即可實(shí)現(xiàn)多頁簽功能,如下圖的 ?vue-element-admin ?就是典型的多頁簽案例。

React 多頁簽本身好實(shí)現(xiàn),難點(diǎn)是沒有官方提供類似 Vue 的 keep-alive 功能,而使用 React Router,路由切換會直接卸載組件,導(dǎo)致無法緩存,用戶的數(shù)據(jù)和行為因此丟失了。
社區(qū)上關(guān)于多頁簽的需求呼聲也非常高,但是如 React 社區(qū)比較出名的中后臺方案 Ant Design Pro 也不支持該功能,兩年沒看,至今仍然有很多 Issue 提出這類需求:

偏右大佬早在 2017 年對此做出了回應(yīng),詳見“能否提供tab切換模式 · Issue #220 · ant-design/ant-design-pro · GitHub”,這個 Isuue 雖然關(guān)閉了,但這些年仍然活躍:

看 ?? 的數(shù)量就知道,用戶其實(shí)對這種回答很不買帳。再來看 2019 年偏右對這個問題的解釋,稍微具體了些:

這個解釋我個人并不完全認(rèn)同。首先說 “tab 模式無法(不適合)進(jìn)行 url 的分享”其實(shí)是不成立的, url 帶路由和參數(shù)就能準(zhǔn)確跳轉(zhuǎn)到對應(yīng)頁面,這在我們系統(tǒng)和 Vue 的多頁簽系統(tǒng)里都是基本功能;而說瀏覽器本身有 tabs 就不需要做到網(wǎng)站內(nèi)部,也比較片面,SPA 的頁面不開瀏覽器 tab 應(yīng)該更符合 Antd 的設(shè)計(jì)價值觀:足不出戶 - Ant Design,就連最新版的 Chrome 都已經(jīng)支持“群組”功能了,讓用戶在 SPA 頁面盡量不開瀏覽器頁簽才應(yīng)該是更好的體驗(yàn)設(shè)計(jì)。
看看社區(qū)其他人的理性分析:

三、方案選型
經(jīng)過一番調(diào)研之后,基本的思路大概有三種:
使用 Redux,數(shù)據(jù)往 store 里面懟,實(shí)現(xiàn)頁面數(shù)據(jù)的”緩存“。 改寫 React Router 源碼,切換路由不卸載,改為隱藏。 使用社區(qū)的輪子,當(dāng)時選了GitHub 里的兩個產(chǎn)品:React Keeper ?和 react-router-cache-route
其實(shí)每種方案都存在一些問題,最終的選擇是使用了排除法。第一種方案的缺點(diǎn)是,由于存在大量的存量項(xiàng)目,而且項(xiàng)目本身的代碼也很多,改造侵入性比較大,不是很好的選擇。第二種的思路和 ?react-router-cache-route ?比較像,就不想重復(fù)造輪子了。第三種選用開源方案其實(shí)當(dāng)時也不太想選擇,別看現(xiàn)在這兩個項(xiàng)目都有 700 多 star,在當(dāng)時 star 數(shù)只有幾十個,而且 Issue 和 Pr 也很少,也就是用戶和貢獻(xiàn)者都不多,所以擔(dān)心會有后續(xù)維護(hù)性的問題以及隱藏的暗坑。
最終同事選擇了 react-router-cache-route,但在當(dāng)時在項(xiàng)目嘗試集成的時候,直接就報(bào)個錯,給了我同事當(dāng)頭一棒,詳見這個 Issue。

同事找到我來排查問題,經(jīng)過定位,發(fā)現(xiàn)是 React 16 的一個 Breaking Change 導(dǎo)致的,從 React 16 版本開始, React 組件可以返回?cái)?shù)組了,而 React 15 不行,詳見我提交的這個 PR。
解決了 react-router-cache-route 在 React 15 版本報(bào)錯問題之后,接下來的工作就是實(shí)現(xiàn)頁簽的 UI 和打開關(guān)閉的邏輯了,注意關(guān)閉需要調(diào)用 ?react-router-cache-route 的卸載緩存 API。
四、還存在什么問題
項(xiàng)目組深度使用 ?react-router-cache-route ?兩年時間了,期間由于 React 和 React Router 版本迭代也出現(xiàn)過一些問題,好在 ?react-router-cache-route 的作者一直保持更新,解決了很多棘手的問題。
但目前總結(jié)起來仍然存在兩個問題,一個是嵌套的 Cache Route 內(nèi)部 Route 無法清除緩存問題,剛才看了一下,這個問題終于有了解,詳見 Issue #64 :

但這個問題大約 1 年時間才有解!
還有一個問題,這個其實(shí)不是 react-router-cache-route 的問題。我們在多頁簽的迭代中增加了相同組件多開功能,這個場景比較常見,比如列表頁點(diǎn)擊鏈接跳轉(zhuǎn)到表單頁,可以同時打開多個表單,這樣在不使用 Redux 是沒有什么問題,但是一旦數(shù)據(jù)存在 Redux 中,多開組件就會有問題,顯示的始終是 store 中最新的數(shù)據(jù),要解決這個問題,需要重構(gòu) Redux 相關(guān)邏輯,比較麻煩。
五、現(xiàn)在 React 多頁簽方案有啥新進(jìn)展嗎
有很長時間沒關(guān)注了,這兩天復(fù)盤看了看相關(guān) Issue,發(fā)現(xiàn)又出現(xiàn)了一些新的輪子,沒有驗(yàn)證過,先放在下面供同學(xué)們參考。如果想要實(shí)現(xiàn)多頁簽功能的同學(xué),還是推薦使用 react-router-cache-route,畢竟我們已經(jīng)穩(wěn)定使用兩年多了,沒有太大問題。
react-router-cache-route (推薦) React Activation (和上面的工具同一個作者,Vue 中 功能在 React 中的實(shí)現(xiàn),配合 babel 預(yù)編譯實(shí)現(xiàn)更穩(wěn)定的 KeepAlive 功能) umi-plugin-keep-alive (上面輪子的 umi 插件) react-keeper (774 star) react-antd-multi-tabs-admin (73 star,Antd多標(biāo)簽頁后臺管理模板) react-live-route (207 star,也是一種緩存路由的輪子) React Ant (232 star,基于Ant Design Pro 2.0 的多標(biāo)簽頁tabs) Ant Design Pro Plus ( 88 star,基于 ant-design-pro 做一些微小的工作) React Admin (83 star,基于 Ant Design React 的管理系統(tǒng)架構(gòu)) ant_pro_tabs (82 star,基于 Ant Design Pro 4 實(shí)現(xiàn)多標(biāo)簽頁面,包括:路由聯(lián)動,列表,多詳情頁共存,自動新增、關(guān)閉標(biāo)簽等功能) Antd Pro Page Tabs ( 54 star,Ant Design Pro 多頁簽,基于 UmiJS ) alita/packages/tabs-layout(基于 umi 的移動端 react 框架的緩存插件)
大家選擇的時候可以考察其原理,star 數(shù),Issue 數(shù),PR 數(shù)等,當(dāng)然,也可以看看他們實(shí)現(xiàn)的原理,學(xué)習(xí)一下這塊的思路也是不錯的。
六、結(jié)語
中后臺類系統(tǒng)多頁簽的需求應(yīng)該是很多的,React 技術(shù)棧目前還沒有大一統(tǒng)的解決方案,目前是輪子齊飛的狀態(tài)。希望本文的經(jīng)驗(yàn)?zāi)軌驇椭酱蠹?,少走彎路?/p>

回復(fù)“加群”與大佬們一起交流學(xué)習(xí)~
點(diǎn)擊“閱讀原文”查看 120+ 篇原創(chuàng)文章
