javascript - React Virtualized 难以理解 overscanIndicesGetter
问题描述
我目前正在使用 React Virtualized 来虚拟化一个列表。需要注意的是,我的列表实际上是一个网格布局,我的组件返回语句如下所示:
所以列表实际上最终呈现了一个网格格式。下面的屏幕截图说明了输出 atm 无论如何。
[ITEM] [ITEM] [ITEM] [ITEM]
[ITEM] [ITEM] [ITEM] [ITEM]
[ITEM] [ITEM] [ITEM] [ITEM]
取决于有多少空间可以使用。AutoResizer 调整我的(虚拟)网格中有多少列,一切都很好。
const getMaxItemsAmountPerRow = (rowWidth, itemWidth) => {
return Math.max(Math.floor(rowWidth / itemWidth), 1);
};
const generateIndexesForRow = (rowIndex, rowWidth, itemWidth, itemsAmount) => {
const result = [];
const maxItemsPerRow = getMaxItemsAmountPerRow(rowWidth, itemWidth);
const startIndex = rowIndex * maxItemsPerRow;
for (
let i = startIndex;
i < Math.min(startIndex + maxItemsPerRow, itemsAmount);
i += 1
) {
result.push(i);
}
return result;
};
const getRowsAmount = (rowWidth, itemWidth, itemsAmount, hasMore) => {
const maxItemsPerRow = getMaxItemsAmountPerRow(rowWidth, itemWidth);
const returnVal = Math.ceil(itemsAmount / maxItemsPerRow) + (hasMore ? 1 : 0);
return returnVal;
};
return (
<>
<AutoSizer disableHeight>
{({ width: rowWidth }) => {
const rowCount = getRowsAmount(
rowWidth,
itemWidth,
items.length,
hasMore,
);
return (
<InfiniteLoader
ref={infiniteLoaderRef}
rowCount={rowCount}
isRowLoaded={({ index }) => {
const indexes = generateIndexesForRow(
index,
rowWidth,
itemWidth,
items.length,
);
const allItemsLoaded = indexes.length > 0;
return !hasMore || allItemsLoaded;
}}
loadMoreRows={loadMoreRows}
>
{({ onRowsRendered }) => (
<WindowScroller>
{({ registerChild }) => (
<>
<List
height={calcGridHeight()}
width={rowWidth}
rowCount={rowCount}
overscanRowCount={96}
ref={registerChild}
rowHeight={itemHeight}
onRowsRendered={onRowsRendered}
rowRenderer={({
index,
style,
key,
isVisible,
isScrolling,
}) => {
const itemsForRow = generateIndexesForRow(
index,
rowWidth,
itemWidth,
items.length,
).map((itemIndex) => items[itemIndex]);
return (
<ListRow style={style} key={key} ref={gridRowRef}>
{itemsForRow.map((item, itemIndex) => (
<ListItem key={itemIndex}>
{children(
item,
isVisible,
isScrolling,
itemsForRow.length,
)}
</ListItem>
))}
</ListRow>
);
}}
noRowsRenderer={noRowsRenderer}
/>
</>
)}
</WindowScroller>
)}
</InfiniteLoader>
);
}}
</AutoSizer>
</>
);
children 的 render 属性调用另一个组件来渲染我的项目:
const renderFunc = (item, isVisible, isScrolling) => {
return isVisible ? (
<Item
key={item.id}
item={item}
/>
) : (
<DummyItem />
);
};
但是,我的isVisible
变量(在 react-virtualized 内部生成)被传递到函数中似乎返回 false 有点太早了。
这会在滚动时导致以下行为:
换句话说,即使在缓慢滚动时,我的过度扫描也不够急切——isVisible
以至于返回 true 需要太长时间,我强烈怀疑这是由于我的布局造成的。
切入正题,从四处阅读 - (正确或错误)我认为可能需要调整过扫描索引吸气剂,请参见此处:https ://github.com/bvaughn/react-virtualized/blob/master/docs/ Grid.md#overscanindicesgetter
但是,尽管我一无所知,但我无法完全了解此文档以准确了解它在做什么,以及我可能需要做些什么来解决问题以使我的过度扫描更加急切。您会注意到 overscanRowCount={96} 已添加到列表中,我认为即使在滚动速度较慢的情况下,高数字也应该足以让组件使用额外的 html.. 因此我认为可能overscanIndicesGetter
是我问题的关键。
任何帮助表示赞赏,即使它可以帮助我了解 overscanIndicesGetter 函数以及它在引擎盖下的作用。我尝试了 console.logging 一些内部变量,但我仍然没有更明智,因为它的输出似乎波动很大。
解决方案
1,然后尝试使用其他库react-virtualized
。我会建议[react-virtual][1]
。边界大小要小得多,并且使用React.FC
. (现代反应)。
2,我不确定你是否应该把virtual-list
, 和isVisible
.
解决方案:
像这样的结构:
[ITEM] [ITEM] [ITEM] [ITEM]
[ITEM] [ITEM] [ITEM] [ITEM]
[ITEM] [ITEM] [ITEM] [ITEM]
是一个好的开始。在这种情况下,您还必须跟踪容器width
和每个item
宽度。宽度这个逻辑,你可以按照下面的步骤:
- 跟踪
row
和column
大小。(marshaledList
)。 - 创建一个
rowVirtualizer
和columnVirtualizer
。(取决于marshaledList
)。 - 设置
gap
之间。 - 样式化
list
andgrid
。 - 显示
rowVirtualizer
和columnVirtualizer
元素。
现场演示(处理 20k 个元素):https://codesandbox.io/s/naughty-kepler-vh70n?file=/src/App.js:2501-2506
推荐阅读
- vue.js - 赛普拉斯没有针对和更改 Vuetify v-data-table 组件的“每页行数”
- c++ - CLION:如何从 C++ 源代码生成类图
- reactjs - 为什么防止默认不起作用?handleSubmit 已绑定并且传播不起作用
- android - 高尔夫记分卡界面的最佳布局/容器是什么?
- apache-kafka - 不使用 Kafka Connect 复制架构更改
- r - R代码仅将列从日期时间更改为时间
- django - 我从贝宝获取账单时遇到问题
- javascript - 用 Vite 将 JS 和 CSS 打包成一个文件
- java - demo.war 文件不会在 Tomcat 服务器上运行
- javascript - 在烛台 Google 图表上添加星形图标