mirror of https://github.com/msgbyte/tailchat
feat: 增加KeepAliveOverlay组件用于缓存iframe
parent
fcc2684a34
commit
373e424e6a
@ -0,0 +1,33 @@
|
||||
import React, { FC } from 'react';
|
||||
import { useKeepAliveStore } from './store';
|
||||
|
||||
export const KeepAliveOverlayHost: FC<React.PropsWithChildren> = (props) => {
|
||||
const cachedComponents = useKeepAliveStore((state) => state.cachedComponents);
|
||||
|
||||
return (
|
||||
<>
|
||||
{props.children}
|
||||
|
||||
<div className="keep-alive-overlay-host">
|
||||
{Object.entries(cachedComponents).map(([cacheId, cacheItem]) => {
|
||||
const { visible, element, rect } = cacheItem;
|
||||
|
||||
return (
|
||||
<div
|
||||
id={`cache-${cacheId}`}
|
||||
style={{
|
||||
display: visible ? 'block' : 'none',
|
||||
...rect,
|
||||
position: 'fixed',
|
||||
}}
|
||||
key={cacheId}
|
||||
>
|
||||
{element}
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
};
|
||||
KeepAliveOverlayHost.displayName = 'KeepAliveOverlayHost';
|
@ -0,0 +1,3 @@
|
||||
组件状态缓存, 使用覆盖层的方式来保持存活(类似小程序叠加原生程序的感觉)
|
||||
|
||||
支持`iframe`的渲染缓存.
|
@ -0,0 +1,2 @@
|
||||
export { KeepAliveOverlayHost } from './KeepAliveOverlayHost';
|
||||
export { withKeepAliveOverlay } from './withKeepAliveOverlay';
|
@ -0,0 +1,79 @@
|
||||
import type React from 'react';
|
||||
import create from 'zustand';
|
||||
import { immer } from 'zustand/middleware/immer';
|
||||
|
||||
interface ElementDisplayRect {
|
||||
left: number;
|
||||
top: number;
|
||||
width: number;
|
||||
height: number;
|
||||
}
|
||||
|
||||
interface KeepAliveState {
|
||||
cachedComponents: Record<
|
||||
string,
|
||||
{
|
||||
visible: boolean;
|
||||
element: React.ReactElement;
|
||||
rect: ElementDisplayRect;
|
||||
}
|
||||
>;
|
||||
mount: (cacheId: string, element: React.ReactElement) => void;
|
||||
show: (cacheId: string) => void;
|
||||
hide: (cacheId: string) => void;
|
||||
updateRect: (cacheId: string, rect: ElementDisplayRect) => void;
|
||||
}
|
||||
|
||||
export const useKeepAliveStore = create<KeepAliveState>()(
|
||||
immer((set) => ({
|
||||
cachedComponents: {},
|
||||
mount: (cacheId, element) => {
|
||||
set((state) => {
|
||||
const cachedComponents = state.cachedComponents;
|
||||
if (cachedComponents[cacheId]) {
|
||||
// 已经挂载过
|
||||
state.cachedComponents[cacheId].visible = true;
|
||||
return;
|
||||
}
|
||||
|
||||
cachedComponents[cacheId] = {
|
||||
visible: true,
|
||||
element,
|
||||
rect: {
|
||||
left: 0,
|
||||
top: 0,
|
||||
width: 0,
|
||||
height: 0,
|
||||
},
|
||||
};
|
||||
});
|
||||
},
|
||||
show: (cacheId) => {
|
||||
set((state) => {
|
||||
if (!state.cachedComponents[cacheId]) {
|
||||
return;
|
||||
}
|
||||
|
||||
state.cachedComponents[cacheId].visible = true;
|
||||
});
|
||||
},
|
||||
hide: (cacheId) => {
|
||||
set((state) => {
|
||||
if (!state.cachedComponents[cacheId]) {
|
||||
return;
|
||||
}
|
||||
|
||||
state.cachedComponents[cacheId].visible = false;
|
||||
});
|
||||
},
|
||||
updateRect: (cacheId: string, rect: ElementDisplayRect) => {
|
||||
set((state) => {
|
||||
if (!state.cachedComponents[cacheId]) {
|
||||
return;
|
||||
}
|
||||
|
||||
state.cachedComponents[cacheId].rect = rect;
|
||||
});
|
||||
},
|
||||
}))
|
||||
);
|
@ -1,17 +1,20 @@
|
||||
import React from 'react';
|
||||
import { withKeepAliveOverlay } from './KeepAliveOverlay';
|
||||
|
||||
interface WebviewProps {
|
||||
url: string;
|
||||
className?: string;
|
||||
style?: React.CSSProperties;
|
||||
url: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* 网页渲染容器
|
||||
*/
|
||||
export const Webview: React.FC<WebviewProps> = React.memo((props) => {
|
||||
return (
|
||||
<iframe className={props.className} style={props.style} src={props.url} />
|
||||
export const Webview: React.FC<WebviewProps> =
|
||||
withKeepAliveOverlay<WebviewProps>(
|
||||
(props) => {
|
||||
return <iframe className="w-full h-full bg-white" src={props.url} />;
|
||||
},
|
||||
{ cacheId: (props) => props.url }
|
||||
);
|
||||
});
|
||||
Webview.displayName = 'Webview';
|
||||
|
Loading…
Reference in New Issue