什么是 Tanstack Virtual?
Tanstack Virtual是一个虚拟化库,用于高效地呈现大型滚动元素。
该技术是在真实 DOM 中只呈现一定数量的元素,无论数量有多少。在 DOM 中渲染的元素越多,性能就会在某一点上下降,所以如果你有很多元素要显示,不妨试试这种虚拟化技术。
Tanstack 并不是唯一的虚拟化库,还有其他一些库,如 react-virtualised 和 react-window。
问题
以前,我们使用的是上图这样的网格,根据视口的不同,显示的卡片数量也不同。
正如您在 Tanstack Virtual 示例中看到的,Tanstack Virtual 允许您将滚动 div 中的项目应用为绝对项目,并通过变换调整其位置。
换句话说,这不仅仅是将Virtualiser
放在父对象顶部的问题,我们以前就是这样做的。有了 Tanstack Virtual,我们需要确保一行或一列中只能有一个元素。
解决方案
现有的列表项是一个一维数组,我们只需对其进行映射即可呈现。
const itemList = [item1, item2, item3, item4, item5, item6, item7];
返回 <div className='grid grid-cols-1 tablet:grid-cols-3 desktop: grid-cols-5'>
itemList.map(item => <Card item={item} />)
</div> </div>
如上所述,我们只需要在一行中放入一个元素,因此我们对代码进行了如下修改。
let columnSize = 3; // 1, 3, 5
const chunkedItemList = chunkArray(itemList, columnSize);
// [[item1, item2, item3], [item4, item5, item6], [item7]].
返回 <div
chunkedItemList.map(list => <div className='grid grid-cols-1 tablet:grid-cols-3 desktop: grid-cols-5'>
{list.map(item => <Card item={item} />)} </div>)
</div>)
</div
我们通过 columnSize 将现有的项目列表从一维数组转换为二维数组。
图示如下。
你唯一需要担心的是确保每行只有一个元素,以及你想在这一个元素中放入多少项!
实际代码如下
const [columnSize, setColumnSize] = useState(COLUMN_SIZE.desktop);
const list = chunkArray(
flatPages(data) ?
列大小
);
const rowVirtualiser = useVirtualiser({
count: list?.length、
getScrollElement: () => document.getElementById("main-section")、
estimateSize: () => 390、
overscan: 1、
});
useEffect(() => {
if (isLabtop) setColumnSize(COLUMN_SIZE.labtop);
else if (isMobile) setColumnSize(COLUMN_SIZE.mobile);
else setColumnSize(COLUMN_SIZE.desktop);
}, [isLabtop, isMobile]);
{ }
rowVirtualizer.getVirtualItems()?.map((virtualRow) => {
const row = list[virtualRow.index];
if (!row) return null;
返回 (
<div
key={virtualRow.key} <div
className={`absolute top-0 left-0 w-full`}
style={{
transform:translateY(${virtualRow.start}px)`、
}}
>
<div className="grid grid-cols-1 laptop:grid-cols-3 desktop:grid-cols-5 w-full gap-6 place-items-center items-stretch">
{row.map((item) => (
<Card
key={item.designId}
item={item}
isVault={isVault}
/>.
))}
</div> </div
</div
);
});
}
因此,我们只能在实际 DOM 中虚拟绘制其中的一部分,如下所示!