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,所以我也放棄了。可以看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 的渲染位置生成唯一的標識符。
{
"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是自定義的屬性,用來標識是否 緩存。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";
// 封裝一層 專門負責顯示頁面標題
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 }
// 專門負責顯示頁面標題
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-Native之TextInput組件的設(shè)置以及如何獲取輸入框的內(nèi)容
這篇文章主要介紹了React-Native之TextInput組件的設(shè)置以及如何獲取輸入框的內(nèi)容問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2023-05-05
react-native 封裝視頻播放器react-native-video的使用
本文主要介紹了react-native 封裝視頻播放器react-native-video的使用,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2023-01-01
react事件回調(diào)中使用防抖失敗的常見錯誤和正確使用方式
這篇文章主要介紹了react事件回調(diào)中使用防抖失敗的常見錯誤和正確使用方式,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2025-06-06
React Native 自定義下拉刷新上拉加載的列表的示例
本篇文章主要介紹了React Native 自定義下拉刷新上拉加載的列表的示例,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2018-03-03

