You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React无限滚动组件:offsetHeight+scrollTop≠scrollHeight的异常问题

React无限滚动组件在浏览器非标准缩放时无法触发加载的问题解决

问题描述

开发React无限滚动组件时,通过offsetHeight + scrollTop == scrollHeight判断是否滚动至底部,仅在125%、100%、75%、67%缩放比例下正常;但在110%、90%、80%等缩放比例时,滚动到底部时offsetHeight + scrollTop的总和始终略小于scrollHeight,导致无法触发后续加载逻辑。

控制台输出示例:

110%缩放时:
690.9090881347656 == 696
694.5454406738281 == 696
695.757568359375 == 696

100%缩放时:
694.6666564941406 == 696
695.3333435058594 == 696
696 == 696
ok

90%缩放时:
694.0740966796875 == 696
694.8148498535156 == 696
695.5555725097656 == 696

原核心代码:

const handleScroll = async (e) => {
  const { offsetHeight, scrollTop, scrollHeight } = e.target;
  console.log(offsetHeight + scrollTop + " ==  " + scrollHeight);
  if (offsetHeight + scrollTop == scrollHeight) {
    console.log("ok");
    setStep((prev) => prev + step);
    fetchData(nowStep + step);
  }
};

return (
  <div
    onScroll={handleScroll}
    style={{
      height: height,
      overflowY: "scroll",
      overflowX: "hidden",
      width: "100%",
      padding: 0,
      margin: 0,
      textAlign: "center",
    }}
  >
    {children}
  </div>
)

问题原因

浏览器缩放时,scrollTop和offsetHeight会因为像素渲染精度产生小数(比如110%缩放时的695.757...),而scrollHeight通常是元素内容的实际高度(多为整数或更精确的整数值)。直接使用严格相等判断,会因为微小的数值差导致条件不成立。

解决方案

放弃严格相等判断,改用容差范围匹配,允许数值存在极小的误差(比如小于1px的差距),或者对数值进行取整处理。以下是两种可行的修改方式:

方式1:使用容差判断(推荐)

判断offsetHeight + scrollTop是否接近scrollHeight,允许1px以内的误差:

const handleScroll = async (e) => {
  const { offsetHeight, scrollTop, scrollHeight } = e.target;
  const scrollBottom = offsetHeight + scrollTop;
  console.log(scrollBottom + " ==  " + scrollHeight);
  // 允许1px以内的误差,避免缩放导致的精度问题
  if (scrollBottom >= scrollHeight - 1) {
    console.log("ok");
    setStep((prev) => prev + step);
    fetchData(nowStep + step);
  }
};

方式2:对数值取整后判断

将scrollBottom和scrollHeight都取整后再做相等判断:

const handleScroll = async (e) => {
  const { offsetHeight, scrollTop, scrollHeight } = e.target;
  const scrollBottom = Math.round(offsetHeight + scrollTop);
  const roundedScrollHeight = Math.round(scrollHeight);
  console.log(scrollBottom + " ==  " + roundedScrollHeight);
  if (scrollBottom === roundedScrollHeight) {
    console.log("ok");
    setStep((prev) => prev + step);
    fetchData(nowStep + step);
  }
};

补充说明

  • 容差值可以根据实际场景调整,一般1px足够覆盖浏览器缩放带来的精度误差;
  • 也可以使用Math.abs(scrollBottom - scrollHeight) < 1的方式进行判断,逻辑更直观。

内容的提问来源于stack exchange,提问作者Nguyễn Tuấn Kiệt

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.21 11:15:44