react数据懒加载如何实现
React 数据懒加载实现方法
使用 React.lazy 和 Suspense 实现组件懒加载
React.lazy 允许动态导入组件,配合 Suspense 实现懒加载效果。适用于路由组件或大型组件。
import React, { Suspense } from 'react';
const LazyComponent = React.lazy(() => import('./LazyComponent'));
function App() {
return (
<div>
<Suspense fallback={<div>Loading...</div>}>
<LazyComponent />
</Suspense>
</div>
);
}
图片懒加载实现
通过 IntersectionObserver API 监听元素是否进入视口,动态加载图片资源。
import React, { useEffect, useRef } from 'react';
function LazyImage({ src, alt }) {
const imgRef = useRef();
useEffect(() => {
const observer = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
const img = entry.target;
img.src = img.dataset.src;
observer.unobserve(img);
}
});
});
observer.observe(imgRef.current);
return () => observer.disconnect();
}, []);
return <img ref={imgRef} data-src={src} alt={alt} />;
}
数据分页加载
结合滚动事件或按钮点击实现数据分批加载,常见于长列表场景。
import React, { useState, useEffect } from 'react';
function LazyList() {
const [items, setItems] = useState([]);
const [page, setPage] = useState(1);
const loadMore = () => {
fetch(`/api/items?page=${page}`)
.then(res => res.json())
.then(data => {
setItems(prev => [...prev, ...data]);
setPage(prev => prev + 1);
});
};
useEffect(() => {
loadMore();
}, []);
return (
<div>
<ul>
{items.map(item => (
<li key={item.id}>{item.name}</li>
))}
</ul>
<button onClick={loadMore}>Load More</button>
</div>
);
}
自定义 Hook 实现数据懒加载
封装可复用的懒加载逻辑,适用于各种数据加载场景。
import { useState, useEffect } from 'react';
function useLazyLoad(loadFn, initialData = []) {
const [data, setData] = useState(initialData);
const [loading, setLoading] = useState(false);
const [hasMore, setHasMore] = useState(true);
const loadMore = async () => {
if (loading || !hasMore) return;
setLoading(true);
const newData = await loadFn();
setData(prev => [...prev, ...newData]);
setHasMore(newData.length > 0);
setLoading(false);
};
return { data, loading, hasMore, loadMore };
}
虚拟列表优化
对于超长列表,使用虚拟列表技术只渲染可见区域元素,大幅提升性能。
import { FixedSizeList as List } from 'react-window';
function VirtualList({ items }) {
return (
<List
height={500}
itemCount={items.length}
itemSize={50}
width={300}
>
{({ index, style }) => (
<div style={style}>
{items[index]}
</div>
)}
</List>
);
}
注意事项
- 懒加载组件需搭配
Suspense使用并提供 fallback UI - 图片懒加载需考虑占位符和加载失败处理
- 分页加载需注意重复请求和边界条件处理
- 虚拟列表需准确计算元素尺寸
- 所有懒加载实现都应考虑错误处理机制







