带有reactjs的虚拟列表

问题描述 投票:0回答:1

最近我碰到了reat-window库,它很棒而且很方便。这让我想到了它的构建方式,因此我决定尝试一下并构建自己的虚拟化列表

但是列表只能滚动到项目“ 60”。想知道我的索引计算出了什么问题,并从react-window看代码,似乎我们正在做类似的事情src1 src2

任何想法我的索引计算有什么问题

import React, { useMemo, useCallback, useState } from 'react';

const ListItem = ({ val, height }) => {
  return <li style={{ height: `${height}px` }}>{val}</li>;
};

const ITEM_HEIGHT = 20;
const CONTAINER_HEIGHT = 300;
const BUFFER = Math.ceil(CONTAINER_HEIGHT / ITEM_HEIGHT);

export const App = () => {
  const [scrollTop, setScrollTop] = useState(0);

  const allItems = useMemo(() => {
    const items = [];
    for (let i = 0; i < 500; i++) {
      items.push(<ListItem val={i} height={ITEM_HEIGHT} />)
    }
    return items;
  }, [ITEM_HEIGHT]);

  const onScrollHandler = useCallback((event) => {
    setScrollTop(event.currentTarget.scrollTop);
  }, [allItems, setScrollTop]);

  // start index = (total scrolled pixel / row height) - buffer
  const start = Math.max(0, Math.floor(scrollTop / ITEM_HEIGHT) - BUFFER);
  // end index   = (total scrolled pixel + list height) / row height + buffer
  const end = Math.min(allItems.length - 1, Math.ceil((scrollTop + CONTAINER_HEIGHT) / ITEM_HEIGHT) + BUFFER);
  const itemsToBeRender = allItems.slice(start, end);

  return (
    <div
      style={{ overflowY: "scroll" }}
      onScroll={onScrollHandler}>
      <ul
        style={{ height: `${CONTAINER_HEIGHT}px` }}
      >
        {itemsToBeRender}
      </ul>
    </div>
  );
};
javascript reactjs listview react-virtualized
1个回答
0
投票

我做了一些Google搜索,发现了this article。添加“位置”属性后,一切正常。

import React, { useMemo, useCallback, useState } from 'react';

const ITEM_HEIGHT = 20;
const CONTAINER_HEIGHT = 300;
const BUFFER = Math.ceil(CONTAINER_HEIGHT / ITEM_HEIGHT);

export const App = () => {
  const [scrollTop, setScrollTop] = useState(0);

  const allItems = useMemo(() => {
    const items = [];
    for (let i = 0; i < 200; i++) {
      const style = {
        height: `${ITEM_HEIGHT}px`,
        position: "absolute",
        top: `${i * ITEM_HEIGHT}px`,
      };
      items.push(<li key={i} style={style} >{i}</li>)
    }
    return items;
  }, [ITEM_HEIGHT]);

  const onScrollHandler = useCallback((event) => {
    setScrollTop(event.currentTarget.scrollTop);
  }, [allItems, setScrollTop]);

  // fake we have a lots of item, so that the scroll bar will always show up
  const fullHeight = allItems.length * ITEM_HEIGHT;
  const start = Math.max(0, Math.floor(scrollTop / ITEM_HEIGHT) - BUFFER);
  const end = Math.min(
    allItems.length - 1,
    Math.floor((scrollTop + CONTAINER_HEIGHT) / ITEM_HEIGHT) + BUFFER);

  const itemsToBeRender = allItems.slice(start, end + 1);

  return (
    <div
      style={{ overflowY: "scroll", height: `${CONTAINER_HEIGHT}px` }}
      onScroll={onScrollHandler}>
      <ul
        style={{ height: `${fullHeight}px`, position: "relative" }}
      >
        {itemsToBeRender}
      </ul>
    </div>
  );
};
© www.soinside.com 2019 - 2024. All rights reserved.