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

如何实现JavaScript中多个scroll()链式调用,逐个滚动到列表项?

平滑滚动遍历列表项并停顿的问题

期望行为

滚动到每个listitem,停顿1秒后滚动到下一个listitem,直至列表末尾。

复现代码

HTML

<div id="pane-side">
  <div>
    <div>
      <div>
        <div role="listitem"></div>
        <div role="listitem"></div>
        <div role="listitem"></div>
        <div role="listitem"></div>
        <div role="listitem"></div>
        <div role="listitem"></div>
        <div role="listitem"></div>
      </div>
    </div>
  </div>
</div>

JavaScript

const sleep = (time) => new Promise(res => setTimeout(res, time, "done sleeping"));

let elm = document.querySelector('#pane-side');
let listitems = elm.children[0].children[0].children
for (let index = 0; index < listitems.length; index++) {
  const y = listitems[index].getBoundingClientRect().top + window.scrollY;
  elm.scroll({
    top: y,
    behavior: 'smooth'
  });
  sleep(1000).then(msg => console.log(msg));
}

问题现象

代码仅会滚动到第一个listitem,之后便不再执行滚动操作。

调试尝试

曾将elm.scroll({..})替换为listitems[index].scrollIntoView({ behavior: "smooth", block: "end", inline: "nearest" });,但该代码甚至一次滚动都未执行。


解决方案

问题原因

  1. 原for循环为同步执行,所有滚动指令会在瞬间全部触发,浏览器只会处理最后一次有效指令,导致仅能看到第一次滚动效果。
  2. sleep的异步调用不会阻塞循环,所有停顿操作同时开始计时,无法实现逐个停顿的效果。
  3. 使用scrollIntoView无效,是因为未正确监听滚动容器的滚动结束事件,且容器可能未设置正确的滚动样式(如overflow-y: auto)。

修正代码

// 等待滚动容器的滚动结束事件
const waitForScrollEnd = (element) => {
  return new Promise(resolve => {
    const onScrollEnd = () => {
      element.removeEventListener('scrollend', onScrollEnd);
      resolve();
    };
    element.addEventListener('scrollend', onScrollEnd);
  });
};

// 停顿函数
const sleep = (time) => new Promise(res => setTimeout(res, time));

// 串行执行滚动逻辑
async function scrollThroughItems() {
  const elm = document.querySelector('#pane-side');
  // 用属性选择器更可靠地获取所有listitem
  const listitems = elm.querySelectorAll('[role="listitem"]');

  for (const item of listitems) {
    // 滚动到当前项,确保容器滚动而非视口滚动
    item.scrollIntoView({ behavior: 'smooth', block: 'start' });
    // 等待滚动完成
    await waitForScrollEnd(elm);
    // 停顿1秒
    await sleep(1000);
  }
}

// 启动滚动
scrollThroughItems();

补充HTML样式(确保滚动容器生效)

给#pane-side添加滚动样式,否则无法看到滚动效果:

<div id="pane-side" style="height: 200px; overflow-y: auto; border: 1px solid #ccc;">
  <div>
    <div>
      <div>
        <div role="listitem" style="height: 150px; background: #f0f0f0; margin: 10px 0;">Item 1</div>
        <div role="listitem" style="height: 150px; background: #f0f0f0; margin: 10px 0;">Item 2</div>
        <div role="listitem" style="height: 150px; background: #f0f0f0; margin: 10px 0;">Item 3</div>
        <div role="listitem" style="height: 150px; background: #f0f0f0; margin: 10px 0;">Item 4</div>
        <div role="listitem" style="height: 150px; background: #f0f0f0; margin: 10px 0;">Item 5</div>
        <div role="listitem" style="height: 150px; background: #f0f0f0; margin: 10px 0;">Item 6</div>
        <div role="listitem" style="height: 150px; background: #f0f0f0; margin: 10px 0;">Item 7</div>
      </div>
    </div>
  </div>
</div>

内容的提问来源于stack exchange,提问作者ishandutta2007

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.06 19:47:39