虚拟列表滚动时元素高度不一致导致错位怎么办?
我用 React 实现了一个虚拟列表,但列表项高度不固定(有的带展开详情,有的没有),滚动一会儿就出现内容错位或者空白。试过用 react-window 的 VariableSizeList,但还是不对。
是不是要手动计算每个 item 的高度?下面是我现在的关键代码:
const rowHeight = (index) => {
return messages[index].expanded ? 120 : 60;
};
return (
<VariableSizeList
height={500}
itemCount={messages.length}
itemSize={rowHeight}
width="100%"
>
{Row}
</VariableSizeList>
);
rowHeight函数思路是对的,但光靠这个还不够。关键是
VariableSizeList需要一个精确的高度缓存机制。每次展开收起详情时,要主动更新对应位置的高度。不然滚动过程中组件算不准实际高度就乱套了。在你的 Row 组件里加上个回调函数,在状态变化(比如展开/收起)时调用
listRef.current.resetAfterIndex(index)强制刷新高度计算。记得把 list 组件 ref 存下来用。浏览器兼容这块问题不大,主要就是性能优化上注意下。折腾虚拟列表真挺费劲的,慢慢来吧。
一个是性能问题,每次计算都要访问 messages[index],这在大数据量时会拖慢渲染速度。建议用缓存机制保存已计算的高度值。
另一个是数据变化时要更新列表。当 messages 变化(比如展开收起操作),需要调用 VariableSizeList 的 resetAfterIndex 方法重新计算从某个索引开始的高度。
我给你个改进版代码:
这样应该能解决你的错位问题。记得别忘了加防抖优化滚动性能。折腾这种列表确实挺费劲的,祝你好运。