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

滚动事件行为异常:无限滚动间歇性停止无响应问题排查

问题排查与修复:无限滚动间歇性停止/无响应

核心问题分析

你的代码存在两个关键问题,直接导致滚动异常:

  • 无限循环的强制滚动:step函数一旦启动,就会通过requestAnimationFrame无限递归调用自己,不管用户是否还在手动滚动,页面都会持续自动滚动。这种强制滚动和用户手动滚动的行为冲突,会让浏览器的滚动机制陷入混乱,出现间歇性停止或无响应。
  • 缺少滚动终止逻辑:没有监听用户停止滚动的行为,也没有终止step循环的机制,导致自动滚动无法停止,进一步加剧了滚动冲突。

另外,scroll事件是高频触发事件,每次滚动都会触发多次,虽然不是核心问题,但也会增加不必要的判断开销。

修复方案

  1. 添加滚动终止逻辑:用定时器在用户停止滚动一段时间后(比如200ms),终止自动滚动循环。
  2. 严格控制滚动启停:仅在用户主动滚动且当前无自动滚动时启动,同时在用户停止滚动后及时终止。
  3. 用cancelAnimationFrame终止循环:保存requestAnimationFrame的ID,需要停止时调用该方法终止递归,避免无效循环。

修正后的代码

let scrollStarted = false;
let animationId = null;
let scrollTimer = null;

const step = () => {
  window.scrollBy(0, 5);
  animationId = window.requestAnimationFrame(step);
};

const startAutoScroll = () => {
  if (!scrollStarted) {
    scrollStarted = true;
    animationId = window.requestAnimationFrame(step);
  }
};

const stopAutoScroll = () => {
  if (scrollStarted) {
    scrollStarted = false;
    window.cancelAnimationFrame(animationId);
  }
};

document.addEventListener('scroll', () => {
  // 用户滚动时重置停止计时
  clearTimeout(scrollTimer);
  
  startAutoScroll();
  
  // 用户停止滚动200ms后终止自动滚动
  scrollTimer = setTimeout(() => {
    stopAutoScroll();
  }, 200);
});

额外说明

  • 定时器的时间可根据需求调整,200ms是兼顾体验和性能的合理阈值。
  • 保存animationId是为了精准终止对应循环,避免内存泄漏或无效运行。
  • 移除了原代码中未使用的ay和vy变量,简化逻辑。

内容的提问来源于stack exchange,提问作者Сережа Белоус

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.25 09:30:43