44 lines
1.3 KiB
TypeScript
44 lines
1.3 KiB
TypeScript
import React, { useRef } from 'react';
|
|
import { useLocation, useOutlet } from 'react-router';
|
|
|
|
const MAX_CACHED_PAGES = 30;
|
|
|
|
/**
|
|
* 路由保活:切换页面时保留已访问页面的组件实例(输入、滚动、弹窗状态不丢失)。
|
|
* 隐藏页面仍挂载在 DOM 中,仅通过 display:none 隐藏。
|
|
*/
|
|
export const RouteKeeper: React.FC = () => {
|
|
const location = useLocation();
|
|
const outlet = useOutlet();
|
|
const cacheRef = useRef<Map<string, React.ReactNode>>(new Map());
|
|
const orderRef = useRef<string[]>([]);
|
|
// 仅以 pathname 作为缓存键:页面内部通过 URL 参数同步状态时不会
|
|
// 产生第二个实例,切回时也不会因此重挂载。
|
|
const pageKey = location.pathname;
|
|
|
|
if (outlet && !cacheRef.current.has(pageKey)) {
|
|
cacheRef.current.set(pageKey, outlet);
|
|
orderRef.current.push(pageKey);
|
|
if (orderRef.current.length > MAX_CACHED_PAGES) {
|
|
const oldest = orderRef.current.shift();
|
|
if (oldest && oldest !== pageKey) cacheRef.current.delete(oldest);
|
|
}
|
|
}
|
|
|
|
return (
|
|
<>
|
|
{Array.from(cacheRef.current.entries()).map(([key, node]) => (
|
|
<div
|
|
key={key}
|
|
className="route-keeper-page"
|
|
style={{ display: key === pageKey ? undefined : 'none' }}
|
|
>
|
|
{node}
|
|
</div>
|
|
))}
|
|
</>
|
|
);
|
|
};
|
|
|
|
export default RouteKeeper;
|