4

我意识到滚动事件中的 javascript 有点奇怪。

直到现在,我一直坚信只要滚动位置发生变化,它就会直接触发。
而且因为 javascript 是阻塞的,所以回调总是第一个被执行的东西,也是第一个“看到”这个新值的函数——至少我是这么认为的。

在这里,我进行了简单的设置,其中全局值在滚动时更新为当前滚动位置。然后有一个区间比较两者。
现在,如果您快速滚动,有时确实会发生,缓存值与实际返回的滚动位置不同。

// cache scroll pos
var scrollPos = 0;
// update on scroll
window.onscroll = function () {
    scrollPos = scrollTop();
};
// compare on interval
setInterval(function () {
    if (scrollPos != scrollTop()) {
        console.log("Out of sync!  cached:", scrollPos, "| actual:", scrollTop());
    }
}, 100);

小提琴: http: //jsfiddle.net/71vdx4rv/2/
您可以尝试快速滚动或使用按钮。[在 Chrome、Safari、FF、Opera 上测试]

为什么在回调之前执行间隔函数并知道“新”滚动位置?
有人可以向我解释一下吗?

4

1 回答 1

4

直到现在,我一直坚信只要滚动位置发生变化,它就会直接触发。

不幸的是(显然)情况并非如此。虽然DOM 3 确实说明了

scroll当文档视图或元素被滚动时,用户代理必须调度 [the ] 事件。此事件类型在滚动发生后调度。

这并不意味着“立即”。CSSOM草案阐明

[要执行滚动,重复运行这些步骤]:

  1. 执行 [平滑或即时] 滚动boxposition
  2. 将要运行的任务排队task,除非要运行的任务task在队列中。

[在哪里会在相应的目标task上触发事件]scroll

“排队任务”明确表示事件是异步调度的,因此在滚动事件触发任务之前执行等待任务(如您的计时器)时,滚动位置可能已经更改。

此外,在执行平滑滚动时,允许浏览器在任意时间跨度内多次更改滚动位置,然后将任务排队以触发scroll事件。

于 2014-09-05T12:57:03.280 回答