fix: 用 IntersectionObserver 替代 scroll 事件实现瀑布流
scroll 事件在某些布局下不触发,改用 IntersectionObserver 监听列表底部哨兵元素,进入视口时自动加载下一页,更可靠。 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -115,8 +115,6 @@ export default function MonitoringView() {
|
||||
const [loadingMore, setLoadingMore] = useState(false);
|
||||
const [showBackToTop, setShowBackToTop] = useState(false);
|
||||
const PAGE_SIZE = 50;
|
||||
const listEndRef = useRef<HTMLDivElement>(null);
|
||||
const scrollContainerRef = useRef<HTMLDivElement>(null);
|
||||
|
||||
const departments = filterOptions.departments;
|
||||
const plateNumbers = filterOptions.plates;
|
||||
@@ -178,26 +176,34 @@ export default function MonitoringView() {
|
||||
loadFirstPage();
|
||||
}, [loadFirstPage]);
|
||||
|
||||
// 滚动触底检测 + 回到顶部按钮
|
||||
// 触底检测:用 IntersectionObserver 监听哨兵元素
|
||||
const loadMoreRef = useRef(loadMore);
|
||||
loadMoreRef.current = loadMore;
|
||||
const sentinelRef = useRef<HTMLDivElement>(null);
|
||||
|
||||
useEffect(() => {
|
||||
const sentinel = sentinelRef.current;
|
||||
if (!sentinel) return;
|
||||
const observer = new IntersectionObserver(
|
||||
(entries) => {
|
||||
if (entries[0].isIntersecting) {
|
||||
loadMoreRef.current();
|
||||
}
|
||||
},
|
||||
{ rootMargin: '200px' }
|
||||
);
|
||||
observer.observe(sentinel);
|
||||
return () => observer.disconnect();
|
||||
}, []);
|
||||
|
||||
// 回到顶部按钮
|
||||
useEffect(() => {
|
||||
const handleScroll = () => {
|
||||
const scrollY = window.scrollY || document.documentElement.scrollTop;
|
||||
setShowBackToTop(scrollY > 400);
|
||||
const scrollHeight = document.documentElement.scrollHeight;
|
||||
const clientHeight = window.innerHeight;
|
||||
if (scrollHeight - scrollY - clientHeight < 300) {
|
||||
loadMoreRef.current();
|
||||
}
|
||||
};
|
||||
window.addEventListener('scroll', handleScroll, { passive: true });
|
||||
document.addEventListener('scroll', handleScroll, { passive: true });
|
||||
return () => {
|
||||
window.removeEventListener('scroll', handleScroll);
|
||||
document.removeEventListener('scroll', handleScroll);
|
||||
};
|
||||
return () => window.removeEventListener('scroll', handleScroll);
|
||||
}, []);
|
||||
|
||||
const scrollToTop = () => {
|
||||
@@ -802,7 +808,8 @@ export default function MonitoringView() {
|
||||
<span className="text-[10px] font-bold text-slate-300">已加载全部 {total} 条</span>
|
||||
</div>
|
||||
)}
|
||||
<div ref={listEndRef} />
|
||||
{/* 哨兵元素:进入视口时触发加载更多 */}
|
||||
<div ref={sentinelRef} className="h-1" />
|
||||
</div>
|
||||
|
||||
{/* 回到顶部按钮 */}
|
||||
|
||||
Reference in New Issue
Block a user