已发布作品可二次编辑
This commit is contained in:
@@ -15,6 +15,7 @@ type RouteImageReadyGateProps = {
|
||||
|
||||
const IMAGE_GATE_QUIET_MS = 140;
|
||||
const IMAGE_GATE_MIN_VISIBLE_WAIT_MS = 260;
|
||||
const IMAGE_GATE_MAX_BLOCK_MS = 1400;
|
||||
const IMAGE_PRELOAD_TIMEOUT_MS = 12000;
|
||||
|
||||
const settledImageUrls = new Set<string>();
|
||||
@@ -66,7 +67,7 @@ function preloadImageUrl(url: string) {
|
||||
|
||||
/**
|
||||
* 路由首屏图片门闩:业务页面先真实挂载但不可见,
|
||||
* 等当前 DOM 中已发现的图片全部 settled 后再一次性显示。
|
||||
* 只等待短暂稳定窗口,不再把所有图片加载完成作为首屏硬阻塞。
|
||||
*/
|
||||
export function RouteImageReadyGate({
|
||||
children,
|
||||
@@ -78,6 +79,7 @@ export function RouteImageReadyGate({
|
||||
const scanTimerRef = useRef<number | null>(null);
|
||||
const revealTimerRef = useRef<number | null>(null);
|
||||
const scanVersionRef = useRef(0);
|
||||
const revealedRef = useRef(false);
|
||||
const [ready, setReady] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
@@ -88,6 +90,7 @@ export function RouteImageReadyGate({
|
||||
|
||||
let disposed = false;
|
||||
startTimeRef.current = window.performance.now();
|
||||
revealedRef.current = false;
|
||||
setReady(false);
|
||||
|
||||
const clearScanTimer = () => {
|
||||
@@ -110,27 +113,26 @@ export function RouteImageReadyGate({
|
||||
};
|
||||
|
||||
const scheduleReveal = (version: number) => {
|
||||
if (revealedRef.current) {
|
||||
return;
|
||||
}
|
||||
|
||||
clearRevealTimer();
|
||||
|
||||
const elapsed = window.performance.now() - startTimeRef.current;
|
||||
const delay = Math.max(
|
||||
const preferredDelay = Math.max(
|
||||
IMAGE_GATE_QUIET_MS,
|
||||
IMAGE_GATE_MIN_VISIBLE_WAIT_MS - elapsed,
|
||||
);
|
||||
const maxRemainingDelay = Math.max(0, IMAGE_GATE_MAX_BLOCK_MS - elapsed);
|
||||
const delay = Math.min(preferredDelay, maxRemainingDelay);
|
||||
|
||||
revealTimerRef.current = window.setTimeout(() => {
|
||||
if (disposed || version !== scanVersionRef.current) {
|
||||
return;
|
||||
}
|
||||
|
||||
const pendingUrls = collectRouteImageUrls(root).filter(
|
||||
(url) => !settledImageUrls.has(url),
|
||||
);
|
||||
if (pendingUrls.length > 0) {
|
||||
scheduleScan();
|
||||
return;
|
||||
}
|
||||
|
||||
revealedRef.current = true;
|
||||
setReady(true);
|
||||
}, delay);
|
||||
};
|
||||
@@ -146,23 +148,18 @@ export function RouteImageReadyGate({
|
||||
(url) => !settledImageUrls.has(url),
|
||||
);
|
||||
|
||||
if (pendingUrls.length === 0) {
|
||||
scheduleReveal(version);
|
||||
return;
|
||||
if (pendingUrls.length > 0) {
|
||||
// 首屏慢加载的核心约束:图片可预热,但不能无限期阻塞页面主体可见。
|
||||
pendingUrls.forEach((url) => {
|
||||
void preloadImageUrl(url);
|
||||
});
|
||||
}
|
||||
|
||||
// 已进入页面但新 DOM 批量挂载图片时,先回到等待态,避免图片逐张闪入。
|
||||
setReady(false);
|
||||
void Promise.allSettled(pendingUrls.map(preloadImageUrl)).then(() => {
|
||||
if (disposed || version !== scanVersionRef.current) {
|
||||
return;
|
||||
}
|
||||
scheduleScan();
|
||||
});
|
||||
scheduleReveal(version);
|
||||
}
|
||||
|
||||
const observer = new MutationObserver((mutations) => {
|
||||
if (disposed) {
|
||||
if (disposed || revealedRef.current) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user