douban页面大屏自动预加载第二页

This commit is contained in:
mtvpls
2026-03-27 12:12:58 +08:00
parent 90b4633f6b
commit 068459cc5f

View File

@@ -30,6 +30,7 @@ function DoubanPageClient() {
const [selectorsReady, setSelectorsReady] = useState(false);
const observerRef = useRef<IntersectionObserver | null>(null);
const loadingRef = useRef<HTMLDivElement>(null);
const contentRef = useRef<HTMLDivElement>(null);
const debounceTimeoutRef = useRef<NodeJS.Timeout | null>(null);
// 用于存储最新参数值的 refs
@@ -598,6 +599,34 @@ function DoubanPageClient() {
};
}, [hasMore, isLoadingMore, loading]);
// 首屏如果未被撑满,仅在第一页时额外请求一次下一页
useEffect(() => {
if (
loading ||
!selectorsReady ||
isLoadingMore ||
!hasMore ||
doubanData.length === 0 ||
currentPage !== 0
) {
return;
}
const rafId = window.requestAnimationFrame(() => {
const contentEl = contentRef.current;
if (!contentEl) return;
const rect = contentEl.getBoundingClientRect();
const preloadThreshold = window.innerHeight + 120;
if (rect.bottom < preloadThreshold) {
setCurrentPage(1);
}
});
return () => window.cancelAnimationFrame(rafId);
}, [loading, selectorsReady, isLoadingMore, hasMore, doubanData.length, currentPage]);
// 处理选择器变化
const handlePrimaryChange = useCallback(
(value: string) => {
@@ -781,7 +810,7 @@ function DoubanPageClient() {
</div>
{/* 内容展示区域 */}
<div className='max-w-[95%] mx-auto mt-8 overflow-visible'>
<div ref={contentRef} className='max-w-[95%] mx-auto mt-8 overflow-visible'>
{/* 内容网格 */}
<div className='justify-start grid grid-cols-3 gap-x-2 gap-y-12 px-0 sm:px-2 sm:grid-cols-[repeat(auto-fill,minmax(160px,1fr))] sm:gap-x-8 sm:gap-y-20'>
{loading || !selectorsReady