React實現(xiàn)頁面狀態(tài)緩存(keep-alive)的示例代碼
前言:
因為 react、vue都是單頁面應(yīng)用,路由跳轉(zhuǎn)時,就會銷毀上一個頁面的組件。但是有些項目不想被銷毀,想保存狀態(tài)。
比如:h5項目跳轉(zhuǎn)其他頁面返回時,頁面狀態(tài)不丟失。設(shè)想一個 頁面我滑倒了中間,然后跳轉(zhuǎn)到 詳情頁然后 返回,之前的頁面刷新了,回到頂部了肯定不行(搜索條件之類的消失了,滾動條回到頂部了)!
比如:pc端項目后臺管理項目里點擊時 打開一個頁簽,頁簽切換,狀態(tài)頁會丟失。每次切換頁簽都重新請求了接口。
解決方案:
方案調(diào)研:
經(jīng)過我的調(diào)研:
我找到的 第三放庫有:
react-activation
umi-plugin-keep-alive
umi-plugin-keep-alive-tabs
react-keepalive-router
react-router-cache-route
redux、dva等(狀態(tài)共享插件)
react-keepalive-router、react-router-cache-route:
react-keepalive-router、react-router-cache-route 是個人開發(fā)的,github上issues里的建議也沒及時回答。所以我就放棄了,沒考慮。
Offscreen:
Offscreen是react 18.x出的實驗性api,所以我也放棄了??梢钥?a rel="external nofollow" target="_blank">react Offscreen
不過 此api如果正式使用的話,應(yīng)該是最好的選擇。其原理就是 把頁面 隱藏起來,不銷毀組件樹。其實其他 插件原理也是這樣。
umi-plugin-keep-alive、umi-plugin-keep-alive-tabs:
umi-plugin-keep-alive、umi-plugin-keep-alive-tabs 是umi里的,是阿里開發(fā)的,優(yōu)先考慮的就是這個,但看了 文檔發(fā)現(xiàn) 它基于 react-activation。而且 作者也讓關(guān)注 。
其實 如果你項目是 umi的話 用 umi-plugin-keep-alive也可以(低版本umi可能不行)。antd-pro
若依等等基于umi搭建的庫都可以使用umi-plugin-keep-alive。這個插件 和umi綁定,所以我也放棄了,但應(yīng)該也可以單獨使用(我沒試過)。
redux等狀態(tài)共享插件,需要項目搭建時就使用,原理就是,頁面里不寫 useState和state全都放到 store里。然后對整個store緩存。每次進入頁面 判斷一下有緩存就走緩存,沒有重新請求。像redux之類的都有持久化插件,配合持久化插件就很容易實現(xiàn)。缺點是繁瑣,且破壞了 不優(yōu)雅,頁面里不能寫狀態(tài)。而且 還要額外 記錄滾動條的位置。
react-activation:
所以綜上我選擇了 react-activation 它是路由級別的緩存。
react-activation基礎(chǔ)使用步驟及配置:
React Activation 僅支持 React 16 及以上版本
注意:
1.請勿使用 <React.StrictMode />
2.(React v18+)不要使用 ReactDOMClient.createRoot ,使用 ReactDOM.render 代替, https://github.com/CJY0208/react-activation/issues/225#issuecomment-1311136388
1.安裝 react-activation
yarn add react-activation # or npm install react-activation
(可選,推薦)在 .babelrc 中添加 react-activation/babel 插件
該插件在編譯過程中為每個JSX元素添加了一個 _nk 屬性,以幫助 react-activation 運行時根據(jù) react-node-key 的渲染位置生成唯一的標(biāo)識符。
{ "plugins": [ "react-activation/babel" ] }
如果不想使用Babel,建議每個 聲明一個全局唯一不變的 cacheKey 屬性,以保證該高速緩存的穩(wěn)定性,如下所示:
<KeepAlive cacheKey="UNIQUE_ID" />
2.import KeepAlive 然后包裹要緩存的組件 或者元素。
官網(wǎng)示例:
// App.js import React, { useState } from 'react' import KeepAlive from 'react-activation' function Counter() { const [count, setCount] = useState(0) return ( <div> <p>count: {count}</p> <button onClick={() => setCount(count => count + 1)}>Add</button> </div> ) } function App() { const [show, setShow] = useState(true) return ( <div> <button onClick={() => setShow(show => !show)}>Toggle</button> {show && ( <KeepAlive> <Counter /> </KeepAlive> )} </div> ) } export default App
3.將 外層放置在不會卸載的位置,通常在應(yīng)用入口處
配合路由使用react-activation
1.isCache是自定義的屬性,用來標(biāo)識是否 緩存。true就是改路由需要緩存。
{ path: "/", component: <Initial />, title: "主頁", name: "initPage", isCache: true, cacheKey: "home", }
App.js 入口文件 或者 路由配置頁面里 封裝一層 根據(jù) isCache值來確定是否使用 keepAlive包裹。如下:
import React from "react"; import { BrowserRouter, Routes, Route, HashRouter } from "react-router-dom"; import routes from "./routes.js"; import KeepAlive from "react-activation"; // 封裝一層 專門負責(zé)顯示頁面標(biāo)題 const DomTitle = ({ route }) => { const { title, component, isCache ,cacheKey,name} = route; document.title = title; if (isCache) { return <KeepAlive cacheKey={cacheKey} name={name}>{component}</KeepAlive>; } return <>{component}</>; }; const App = () => { return ( <HashRouter> <Routes> {routes.map((route) => ( <Route key={route.path} path={route.path} //element={route.component } // 專門負責(zé)顯示頁面標(biāo)題 element={<DomTitle route={route} />} /> ))} </Routes> </HashRouter> ); };
還可以手動清除緩存
import { useActivate, useUnactivate, withActivation, withAliveScope, useAliveController, } from "react-activation"; const { drop, dropScope, clear, getCachingNodes } = useAliveController(); console.log(getCachingNodes(), "緩存節(jié)點"); //drop("homePage"); // 手動關(guān)閉某個頁面 // dropScope("detailPage"); dropScope("homePage"); // 參數(shù)就是上面定義的 cacheKey
還需要 將 外層放置在不會卸載的位置,通常在應(yīng)用入口處我的項目時create-react-app 是index.js。
具體 api使用方法和注意事項請看:
具體api可以看(如果 github打不開可以看npm的,npm是英文的,可以用edge瀏覽器 翻譯一下):
以上就是React實現(xiàn)頁面狀態(tài)緩存(keep-alive)的示例代碼的詳細內(nèi)容,更多關(guān)于React頁面狀態(tài)緩存的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
淺談React組件props默認(rèn)值的設(shè)置
本文主要介紹了淺談React組件props默認(rèn)值的設(shè)置,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2023-04-04React中實現(xiàn)組件通信的幾種方式小結(jié)
在構(gòu)建復(fù)雜的React應(yīng)用時,組件之間的通信是至關(guān)重要的,從簡單的父子組件通信到跨組件狀態(tài)同步,不同組件之間的通信方式多種多樣,下面我們認(rèn)識react組件通信的幾種方式,需要的朋友可以參考下2024-04-04