我意识到关于滚动事件的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/ 为什么在回调之前执行间隔功能并知道'新'滚动位置?
有人可以向我解释一下吗?
答案 0 :(得分:4)
直到现在,我始终相信只要滚动位置发生变化,就会直接触发它。
不幸的是(显然)事实并非如此。虽然DOM 3 does state
用户代理必须在滚动文档视图或元素时调度[{1}}]事件。滚动发生后将调度此事件类型。
这并不意味着“立即”。 CSSOM draft clarifies:
[要执行滚动,请重复运行这些步骤]:
- 执行
scroll
到box
的[平滑或即时]滚动。- 将任务排队以运行
醇>position
,除非运行task
的任务在队列中。[其中
task
确实会在相应目标上发起task
个事件
“排队任务”显式意味着事件是异步调度的,因此在滚动事件触发任务之前执行等待任务(如计时器)时,滚动位置可能已经被更改。
此外,在执行平滑滚动时,允许浏览器在任意时间跨度内多次更改滚动位置,然后排队任务以触发scroll
事件。