实现虚拟列表过程中出现滚动条抖动问题该怎么解决?

学习实现虚拟列表的过程中,让类名为holder的元素不占据高度的情况下,发现页面在往下滚动的过程中出现滚动条抖动的问题,并且是反复抽搐,为什么会出现这样的情况

export default function VirtualList() {
  const [position, setPosition] = useState({ start: 0, end: 0 });
  const [data, setData] = useState([]);

  const listBoxRef = useRef();
  const contentRef = useRef();
  const scrollInfo = useRef({
    itemHeight: 60,
    bufferCount: 8,
    renderCount: 0
  });

  useEffect(() => {
    const { itemHeight, bufferCount } = scrollInfo.current;
    const { height } = listBoxRef.current.getBoundingClientRect();
    const renderCount = Math.ceil(height / itemHeight) + bufferCount;
    const dataList = new Array(10000).fill(0).map((_, index) => index + 1);
    scrollInfo.current = { ...scrollInfo.current, renderCount };
    setData(dataList);
    setPosition({ start: 0, end: renderCount });
  }, []);

  const handleScroll = () => {
    const { itemHeight, renderCount } = scrollInfo.current;
    const scrollTop = listBoxRef.current.scrollTop;
    console.log('scrollTop', scrollTop);
    const start = Math.floor(scrollTop / itemHeight);
    const end = start + renderCount;
    // contentRef.current.style.transform = `translate3d(0, ${scrollTop}px, 0)`;
    if (start !== position.start || end !== position.end) {
      setPosition({ start, end });
    }
  };

  console.log(position);
  const { itemHeight } = scrollInfo.current;

  return (
    <div className="list-box" ref={listBoxRef} onScroll={handleScroll}>
      <div
        className="holder"
        style={{ height: `${itemHeight * data.length}px` }}
      ></div>
      <div className="content-area" ref={contentRef}>
        {data.slice(position.start, position.end).map((item) => (
          <div key={item} className="item">
            {item}
          </div>
        ))}
      </div>
    </div>
  );
}
.item {
  list-style: none;
  background-color: #fc4838;
  padding: 10px 20px;
  color: #fff;
  height: 50px;
  line-height: 50px;
  box-sizing: border-box;
  margin-bottom: 10px;
  margin-left: 24px;
  margin-right: 24px;
  font-weight: bold;
  border-radius: 10px;
}
.list-box {
  position: fixed;
  left: 0;
  right: 0;
  top: 20px;
  bottom: 0;
  overflow: scroll;
}
.holder {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
}
阅读 3.9k
1 个回答

浏览器滚动锚点导致,要么你每次滚动后重设scrollTop,要么css取消滚动锚点:overflow-anchor: none

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题