網(wǎng)站首頁 編程語言 正文
一、基于react-route6??useOutlet實現(xiàn)
二、代碼呈現(xiàn)
import React, { useRef, createContext, useContext } from 'react' import { useOutlet, useLocation, matchPath } from 'react-router-dom' import type { FC } from 'react' //在組件外部建立一個Context export const KeepAliveContext = createContext<KeepAliveLayoutProps>({ keepalive: [], keepElements: {} }) //給予頁面緩存設(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 } //判斷當前頁面是否已緩存,是則控制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 } //標簽的顯示與隱藏 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 支持字符串和正則,通過它來判斷,當前頁面是否需要狀態(tài)保持,因為如果整個項目的頁面都保持狀態(tài)的話,對性能是很大的消耗
參數(shù)1為可緩存路徑或正則表達式組成的數(shù)組,參數(shù)2為當前路徑。
若當前路徑在已緩存路徑數(shù)組中或其路徑符合正則表達式則isKeep為true,反之為false
useKeepOutlets
通過判斷當前頁面是否是需要保持的頁面來對頁面 DOM 做一個 hidden
顯隱開關(guān)。
需要注意的是所有被指定狀態(tài)保持的頁面在首次渲染之后,都會被掛載在頁面 DOM 樹上,僅僅是使用 !matchPath(location.pathname, pathname)
控制顯隱。
而沒有被指定狀態(tài)保持的頁面,則是使用 {!isKeep && element}
控制,走 React 組件正常的生命周期。
location
當前路徑信息
element
獲取當前路由組件即當前配置下的嵌套路由組件
useContext<any>(KeepAliveContext)
通過useContext()鉤子函數(shù)獲取Context對象中的屬性,已便于組件之間共享狀態(tài)
isKeep
將當前路徑利用頁面緩存設(shè)置條件判斷是否為已緩存路徑,若符合條件,isKeep為true,則將keepElements Ref中以當前組件路徑名為屬性名的屬性綁定當前路由組件
Object.entries
描述:Object.entries()
返回一個數(shù)組,其元素是與直接在object
上找到的可枚舉屬性鍵值對相對應(yīng)的數(shù)組。屬性的順序與通過手動循環(huán)對象的屬性值所給出的順序相同。
可枚舉:枚舉的功能類似于字面量類型+聯(lián)合類型組合的功能,也可以表示一組明確的可選值
參數(shù):可以返回其可枚舉屬性的鍵值對的對象
返回值:給定對象自身可枚舉屬性的鍵值對數(shù)組
key
保持 key 不變,就不會觸發(fā) React 的重繪
hidden
控制顯示與隱藏開關(guān)
matchPath(location.pathname, pathname)}
所有被指定狀態(tài)保持的頁面在首次渲染之后,都會被掛載在頁面 DOM 樹上,僅僅是使用!matchPath(location.pathname, pathname)
控制顯示隱藏。
//matchPath:參數(shù)1為當前路徑,參數(shù)2為緩存路徑,確定當前路由路徑是否與緩存路徑匹配
而沒有被指定狀態(tài)保持的頁面,則是使用 {!isKeep && element}
控制,走 React 組件正常的生命周期
KeepAliveLayout
為封裝后暴露的組件
FC
React.FC
是函數(shù)式組件,是在TypeScript下使用的一個泛型,全稱為React.FunctionComponent
,React.FC<>
?可檢測指定屬性類型
keepElements
使用?React.useRef<any>({})
?來做頁面數(shù)據(jù)保存的節(jié)點,是因為我們的上下文不被重新渲染的話?keepElements
?就不會被重置,相當于?key
?
dropByCacheKey
dropByCacheKey為清除緩存的函數(shù),通過控制當前組件的ref來銷毀組件
other
const { keepalive, ...other } = props
中...other為其他配置,這里我們直接遍歷繼承即可
Provider
(<KeepAliveContext.Provider value={{ keepalive, keepElements, dropByCacheKey }} {...other} />)
原理:
每個 Context 對象都會返回一個 Provider React 組件,它允許消費組件訂閱 context 的變化。
Provider 接收一個?value
?屬性,傳遞給消費組件。一個 Provider 可以和多個消費組件有對應(yīng)關(guān)系。多個 Provider 也可以嵌套使用,里層的會覆蓋外層的數(shù)據(jù)。
當 Provider 的?value
?值發(fā)生變化時,它內(nèi)部的所有消費組件都會重新渲染
三、使用
import KeepAliveLayout, { useKeepOutlets, KeepAliveContext }from'@/components/KeepAliveLayout' import { useLocation } from 'react-router-dom' import React, { useState, useContext } from 'react' // 使用KeepAliveLayout中的useKeepOutlets獲取當前渲染的頁面內(nèi)容 const Layout = () => { const element = useKeepOutlets() return ( {element} ) } // 使用 KeepAliveLayout 包裹上下文 const App = () => { return ( <KeepAliveLayout keepalive={[/./]}>//不可能組件都緩存吧所以需要設(shè)置緩存條件,可傳可緩存的路徑或正則表達式 // App </KeepAliveLayout> ); } // 使用 useContext 獲取 dropByCacheKey 清除緩存 const Home = () => { const { dropByCacheKey } = useContext<any>(KeepAliveContext); const { pathname } = useLocation(); return ( <button onClick={() => dropByCacheKey(pathname)}>清除緩存</button> ) }
原文鏈接:https://juejin.cn/post/7112316129645133838
相關(guān)推薦
- 2022-06-01 Python?調(diào)用?C++?傳遞numpy?數(shù)據(jù)詳情_python
- 2022-05-13 linq中的聚合操作符_實用技巧
- 2022-12-06 詳解Python的整數(shù)是如何實現(xiàn)的_python
- 2023-07-29 highcharts中g(shù)antt甘特圖的使用
- 2022-09-13 iOS實現(xiàn)手動和自動屏幕旋轉(zhuǎn)_IOS
- 2022-11-14 react使用useImperativeHandle示例詳解_React
- 2022-07-01 tensorflow可視化Keras框架中Tensorboard使用示例_python
- 2022-09-22 繼承關(guān)系下構(gòu)造方法的訪問特點
- 最近更新
-
- window11 系統(tǒng)安裝 yarn
- 超詳細win安裝深度學習環(huán)境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎(chǔ)操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區(qū)別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權(quán)
- redisson分布式鎖中waittime的設(shè)
- maven:解決release錯誤:Artif
- restTemplate使用總結(jié)
- Spring Security之安全異常處理
- MybatisPlus優(yōu)雅實現(xiàn)加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務(wù)發(fā)現(xiàn)-Nac
- Spring Security之基于HttpR
- Redis 底層數(shù)據(jù)結(jié)構(gòu)-簡單動態(tài)字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應(yīng)用詳解
- 聊聊消息隊列,發(fā)送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支