瀑布流长列表滚动卡顿怎么优化?
我用 React 实现了一个图片瀑布流,数据一多滚动就特别卡,试过给每个 item 加 key 但没用。是不是得用虚拟滚动?但瀑布流高度不一致,普通的 react-window 好像不支持……
这是我的简化代码:
const WaterfallList = ({ items }) => {
return (
<div className="columns-2 gap-4">
{items.map(item => (
<div key={item.id} className="break-inside-avoid mb-4">
<img src={item.url} alt="" className="w-full" />
</div>
))}
</div>
);
};
加key没用是因为key只影响React的diff算法,不影响实际DOM数量。
解决方案有两个层面,我先说简单有效的:
第一步:图片懒加载
这是最容易上手的优化,很多卡顿其实是图片同时加载导致的。用Intersection Observer让图片进入可视区域再加载真实URL:
第二步:分页加载
一次不要渲染所有数据,比如每次只加载20-30条,用户滚动到底部再加载更多:
第三步:虚拟滚动(数据量特别大时用)
如果你的数据量达到几千条,上面两个优化可能还不够,需要虚拟滚动。瀑布流的虚拟滚动确实比普通列表复杂,因为每列高度不一致,需要动态计算位置。
原理是这样的:只渲染可视区域内的图片,根据每列的累积高度算出每个item的绝对定位。给你一个简化版的实现思路:
这个虚拟滚动的核心思路是:先根据预估高度把每个item应该放的位置算出来(绝对定位),然后滚动时只渲染落在可视区域附近的那些item。
不过说实话,虚拟滚动实现起来坑比较多。如果你数据量不是特别夸张(几千条以上),前面两步优化通常就够了。实际项目中我更推荐用现成的库,比如react-virtualized或者react-window他们都有社区版的瀑布流解决方案,或者用react-waterfall-layout这个专门为瀑布流设计的库。
你现在先试试前两步,应该能明显改善。有什么问题再问。