Tanstack 虚拟涂抹器

本帖由 DeepL 翻译。如有任何翻译错误,请告知我们!

什么是 Tanstack Virtual?

Tanstack Virtual是一个虚拟化库,用于高效地呈现大型滚动元素。

AnimatedImage.gif

该技术是在真实 DOM 中只呈现一定数量的元素,无论数量有多少。在 DOM 中渲染的元素越多,性能就会在某一点上下降,所以如果你有很多元素要显示,不妨试试这种虚拟化技术。

Tanstack 并不是唯一的虚拟化库,还有其他一些库,如 react-virtualised 和 react-window。

问题

Image.png

以前,我们使用的是上图这样的网格,根据视口的不同,显示的卡片数量也不同。

正如您在 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 将现有的项目列表从一维数组转换为二维数组。

图示如下。

Image.png

你唯一需要担心的是确保每行只有一个元素,以及你想在这一个元素中放入多少项!

实际代码如下

const [columnSize, setColumnSize] = useState(COLUMN_SIZE.desktop);

const list = chunkArray(
  flatPages(data) ?
  列大小
);

const rowVirtualiser = useVirtualiser({
  count: list?.lengthgetScrollElement: () => document.getElementById("main-section")、
  estimateSize: () => 390overscan: 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 中虚拟绘制其中的一部分,如下所示!

AnimatedImage.gif