React-Route6實(shí)現(xiàn)keep-alive效果
一、基于react-route6 useOutlet實(shí)現(xiàn)
二、代碼呈現(xiàn)
import React, { useRef, createContext, useContext } from 'react'
import { useOutlet, useLocation, matchPath } from 'react-router-dom'
import type { FC } from 'react'
//在組件外部建立一個(gè)Context
export const KeepAliveContext = createContext<KeepAliveLayoutProps>({ keepalive: [], keepElements: {} })
//給予頁(yè)面緩存設(shè)置條件判斷
const isKeepPath = (aliveList: any[], path: string) => {
let isKeep = false
aliveList.map(item => {
if (item === path) {
isKeep = true
}
if (item instanceof RegExp && item.test(path)) {
isKeep = true
}
})
return isKeep
}
//判斷當(dāng)前頁(yè)面是否已緩存,是則控制hidden開關(guān)顯示 ,不是則正常渲染
export function useKeepOutlets() {
const location = useLocation()
const element = useOutlet()
const { keepElements, keepalive } = useContext<any>(KeepAliveContext)
const isKeep = isKeepPath(keepalive, location.pathname)
if (isKeep) {
keepElements.current[location.pathname] = element
}
//標(biāo)簽的顯示與隱藏
return <> {
Object.entries(keepElements.current).map(([pathname, element]: any) => (
<div key={pathname}
style={{ height: '100%', width: '100%', position: 'relative', overflow: 'hidden auto' }} className="rumtime-keep-alive-layout"
hidden={!matchPath(location.pathname, pathname)}>
{element}
</div>
))
}
<div hidden={isKeep} style={{ height: '100%', width: '100%', position: 'relative', overflow: 'hidden auto' }} className="rumtime-keep-alive-layout-no">
{!isKeep && element}
</div>
</>
}
//設(shè)置公共組件類型
interface KeepAliveLayoutProps {
keepalive: any[]
keepElements?: any
dropByCacheKey?: (path: string) => void
}
//封裝公共組件
const KeepAliveLayout: FC<KeepAliveLayoutProps> = (props) => {
const { keepalive, ...other } = props
const keepElements = React.useRef<any>({})
function dropByCacheKey(path: string) {
keepElements.current[path] = null
} return (<KeepAliveContext.Provider
value={{ keepalive, keepElements, dropByCacheKey }}
{...other} />)
}
export default KeepAliveLayout
代碼分析
isKeepPath
配置 keepalive 支持字符串和正則,通過它來判斷,當(dāng)前頁(yè)面是否需要狀態(tài)保持,因?yàn)槿绻麄€(gè)項(xiàng)目的頁(yè)面都保持狀態(tài)的話,對(duì)性能是很大的消耗
參數(shù)1為可緩存路徑或正則表達(dá)式組成的數(shù)組,參數(shù)2為當(dāng)前路徑。
若當(dāng)前路徑在已緩存路徑數(shù)組中或其路徑符合正則表達(dá)式則isKeep為true,反之為false
useKeepOutlets
通過判斷當(dāng)前頁(yè)面是否是需要保持的頁(yè)面來對(duì)頁(yè)面 DOM 做一個(gè) hidden 顯隱開關(guān)。
需要注意的是所有被指定狀態(tài)保持的頁(yè)面在首次渲染之后,都會(huì)被掛載在頁(yè)面 DOM 樹上,僅僅是使用 !matchPath(location.pathname, pathname) 控制顯隱。
而沒有被指定狀態(tài)保持的頁(yè)面,則是使用 {!isKeep && element} 控制,走 React 組件正常的生命周期。
location
當(dāng)前路徑信息
element
獲取當(dāng)前路由組件即當(dāng)前配置下的嵌套路由組件
useContext<any>(KeepAliveContext)
通過useContext()鉤子函數(shù)獲取Context對(duì)象中的屬性,已便于組件之間共享狀態(tài)
isKeep
將當(dāng)前路徑利用頁(yè)面緩存設(shè)置條件判斷是否為已緩存路徑,若符合條件,isKeep為true,則將keepElements Ref中以當(dāng)前組件路徑名為屬性名的屬性綁定當(dāng)前路由組件
Object.entries
描述:Object.entries()返回一個(gè)數(shù)組,其元素是與直接在object上找到的可枚舉屬性鍵值對(duì)相對(duì)應(yīng)的數(shù)組。屬性的順序與通過手動(dòng)循環(huán)對(duì)象的屬性值所給出的順序相同。
可枚舉:枚舉的功能類似于字面量類型+聯(lián)合類型組合的功能,也可以表示一組明確的可選值
參數(shù):可以返回其可枚舉屬性的鍵值對(duì)的對(duì)象
返回值:給定對(duì)象自身可枚舉屬性的鍵值對(duì)數(shù)組
key
保持 key 不變,就不會(huì)觸發(fā) React 的重繪
hidden
控制顯示與隱藏開關(guān)
matchPath(location.pathname, pathname)}
所有被指定狀態(tài)保持的頁(yè)面在首次渲染之后,都會(huì)被掛載在頁(yè)面 DOM 樹上,僅僅是使用!matchPath(location.pathname, pathname) 控制顯示隱藏。
//matchPath:參數(shù)1為當(dāng)前路徑,參數(shù)2為緩存路徑,確定當(dāng)前路由路徑是否與緩存路徑匹配
而沒有被指定狀態(tài)保持的頁(yè)面,則是使用 {!isKeep && element} 控制,走 React 組件正常的生命周期
KeepAliveLayout
為封裝后暴露的組件
FC
React.FC是函數(shù)式組件,是在TypeScript下使用的一個(gè)泛型,全稱為React.FunctionComponent,React.FC<> 可檢測(cè)指定屬性類型
keepElements
使用 React.useRef<any>({}) 來做頁(yè)面數(shù)據(jù)保存的節(jié)點(diǎn),是因?yàn)槲覀兊纳舷挛牟槐恢匦落秩镜脑?nbsp;keepElements 就不會(huì)被重置,相當(dāng)于 key
dropByCacheKey
dropByCacheKey為清除緩存的函數(shù),通過控制當(dāng)前組件的ref來銷毀組件
other
const { keepalive, ...other } = props中...other為其他配置,這里我們直接遍歷繼承即可
Provider
(<KeepAliveContext.Provider value={{ keepalive, keepElements, dropByCacheKey }} {...other} />)
原理:
每個(gè) Context 對(duì)象都會(huì)返回一個(gè) Provider React 組件,它允許消費(fèi)組件訂閱 context 的變化。
Provider 接收一個(gè) value 屬性,傳遞給消費(fèi)組件。一個(gè) Provider 可以和多個(gè)消費(fèi)組件有對(duì)應(yīng)關(guān)系。多個(gè) Provider 也可以嵌套使用,里層的會(huì)覆蓋外層的數(shù)據(jù)。
當(dāng) Provider 的 value 值發(fā)生變化時(shí),它內(nèi)部的所有消費(fèi)組件都會(huì)重新渲染
三、使用
import KeepAliveLayout, { useKeepOutlets, KeepAliveContext }from'@/components/KeepAliveLayout'
import { useLocation } from 'react-router-dom'
import React, { useState, useContext } from 'react'
// 使用KeepAliveLayout中的useKeepOutlets獲取當(dāng)前渲染的頁(yè)面內(nèi)容
const Layout = () => {
const element = useKeepOutlets()
return (
{element}
)
}
// 使用 KeepAliveLayout 包裹上下文
const App = () => {
return (
<KeepAliveLayout keepalive={[/./]}>//不可能組件都緩存吧所以需要設(shè)置緩存條件,可傳可緩存的路徑或正則表達(dá)式
// App
</KeepAliveLayout>
);
}
// 使用 useContext 獲取 dropByCacheKey 清除緩存
const Home = () => {
const { dropByCacheKey } = useContext<any>(KeepAliveContext);
const { pathname } = useLocation();
return (
<button onClick={() => dropByCacheKey(pathname)}>清除緩存</button>
)
}
到此這篇關(guān)于React-Route6實(shí)現(xiàn)keep-alive效果的文章就介紹到這了,更多相關(guān)React-Route6 keep-alive 內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
React報(bào)錯(cuò)之組件不能作為JSX組件使用的解決方法
本文主要介紹了React報(bào)錯(cuò)之組件不能作為JSX組件使用的解決方法,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2022-07-07
Yarn安裝項(xiàng)目依賴報(bào)error?An?unexpected?error?occurred:?“XXXXX:E
這篇文章主要為大家介紹了Yarn安裝項(xiàng)目依賴報(bào)error?An?unexpected?error?occurred:?“XXXXX:ESOCKETTIMEOUT”問題解決,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-03-03
react實(shí)現(xiàn)點(diǎn)擊選中的li高亮的示例代碼
本篇文章主要介紹了react實(shí)現(xiàn)選中的li高亮的示例代碼,頁(yè)面上有很多個(gè)li,要實(shí)現(xiàn)點(diǎn)擊到哪個(gè)就哪個(gè)高亮。小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2018-05-05
React中使用react-json-view展示JSON數(shù)據(jù)的操作方法
react-json-view是一個(gè)用于顯示和編輯javascript數(shù)組和JSON對(duì)象的React組件,本文給大家分享React中使用react-json-view展示JSON數(shù)據(jù)的操作方法,感興趣的朋友一起看看吧2023-12-12
Vite?+?React從零開始搭建一個(gè)開源組件庫(kù)
這篇文章主要介紹了Vite?+?React?如何從0到1搭建一個(gè)開源組件庫(kù),本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-06-06
記一次react前端項(xiàng)目打包優(yōu)化的方法
這篇文章主要介紹了記一次react前端項(xiàng)目打包優(yōu)化的方法,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-03-03
React 首頁(yè)加載慢問題性能優(yōu)化案例詳解
這篇文章主要介紹了React 首頁(yè)加載慢問題性能優(yōu)化案例詳解,本篇文章通過簡(jiǎn)要的案例,講解了該項(xiàng)技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下2021-09-09
記錄React使用connect后,ref.current為null問題及解決
記錄React使用connect后,ref.current為null問題及解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-05-05

