Files
gongxue-base/apps/admin/src/components/RouteKeeper.tsx

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;