固定高度虚拟列表

41 阅读1分钟
  const ref = useRef(null);

  //  //可视区域高度
  const [screenHeight, setScreenHeight] = useState(0);

  //  //偏移量
  const [startOffset, setStartOffset] = useState(0);

  //  //起始索引
  const [start, setStart] = useState(0);

  const itemSize = 100;

  const listHeight = itemSize * listData.length;

  const transform = `translate3d(0,${startOffset}px,0)`;

  const visibleCount = Math.ceil(screenHeight / itemSize);
  const visibleData = listData.slice(start, start + visibleCount);

  useEffect(() => {
    setScreenHeight(ref.current.clientHeight);
    setStart(0)
  }, []);
  return (
    <div>
      <div
        ref={ref}
        onScroll={(e) => {
          let scrollTop = ref.current.scrollTop;
          setStart(Math.floor(scrollTop / itemSize));
          setStartOffset(scrollTop - (scrollTop % itemSize));
        }}
        style={{
          height: 600,
          overflow: 'auto',
          position: 'relative',
          WebkitOverflowScrolling: 'touch',
          backgroundColor: "pink"
        }}
      >
        <div
          style={{
            height: listHeight,
            position: 'absolute',
            left: 0,
            top: 0,
            right: 0,
            zIndex: -1
          }}
        ></div>
        <div
          style={{
            transform: transform,
            left: 0,
            right: 0,
            top: 0,
            position: 'absolute',
            textAlign: 'center'
          }}
        >
          {visibleData.map((item) => (
            <div
              key={item.id}
              style={{
                height: itemSize,
                lineHeight: `${itemSize}px`,
                color: '#555',
                boxSizing: 'border-box',
                borderBottom: '1px solid #999'
              }}
            >
              {item.value}
            </div>
          ))}
        </div>
      </div>
    </div>
  );
};

参考:juejin.cn/post/684490…