简体   繁体   English

奇怪/不一致的scrollTop行为

[英]Strange / Inconsistent scrollTop behaviour

I stumbled into this one whilst trying to scroll an element without invoking the normal event handlers 在尝试滚动元素而不调用普通事件处理程序时,我偶然发现了这个

Using both Firefox and IE10 I'm seeing some really strange behaviour in how the scrollTop method is operating. 使用Firefox和IE10我在scrollTop方法的运行方式上看到了一些非常奇怪的行为。 For example, if I set the scrollTop on a div , and aferwards , bind a scroll event handler to the same element, the handler fires immediately. 例如,如果我在divaferwards上设置scrollTop ,将scroll事件处理程序绑定到同一个元素,则处理程序立即触发。 From my testing, this doesn't happen with Chrome, which leads me to think that FF and IE are applying the most miniscule of animations to their scrolls, or this is some kind of bug. 从我的测试来看,这不会发生在Chrome上,这让我觉得FF和IE正在将最微小的动画应用到他们的卷轴上,或者这是某种错误。

See JSFiddle example . 参见JSFiddle示例 Interestingly, if I set a timeout of 1ms before the assignment, the problem goes away . 有趣的是,如果我在分配之前设置1ms的超时, 问题就会消失 I'd love to know what's going on here, and what the best approach is to fix it. 我想知道这里发生了什么,以及解决它的最佳方法是什么。

Update : From the comments below it seems as though this might be recognised to be normal browser behaviour, so I'll update my question to ask what is going on here - please cite some interesting articles which explain this process in more detail . 更新 :从下面的评论看来,似乎这可能被认为是正常的浏览器行为,所以我将更新我的问题,以询问这里发生了什么 - 请引用一些有趣的文章,更详细地解释这个过程

What goes on in IE and FF is the following: IE和FF中发生的事情如下:

  1. The scrollTop property is adjusted scrollTop属性已调整
  2. The scroll event handler is added 添加了滚动事件处理程序
  3. Execution of the function finishes. 执行功能完成。 Now, the browser has time for other things and will render the page. 现在,浏览器有时间处理其他事情并将呈现页面。 The rendering causes both the scroll handler and the scrollTop property to be committed simultaneously. 渲染导致同时提交滚动处理程序和scrollTop属性。 The scrollTop change thus triggers a scroll event which is captured by your handler. 因此,scrollTop更改会触发由处理程序捕获的滚动事件。

This is unlike this code: 这与此代码不同:

var dv = document.getElementsByTagName("div")[0];
dv.scrollTop = dv.scrollHeight;
setTimeout(function(){
    dv.onscroll = function() { 
    console.log("scrolled!");
}, 0);

Where the following happpens: 以下哪些方面很开心:

  1. The scrollTop property is adjusted scrollTop属性已调整
  2. The setTimeout function appends the function that adds the onscroll event handler to the event queue. setTimeout函数附加将onscroll事件处理程序添加到事件队列的函数。 Essentially deferring the execution of the code until timeout processing occurs (see also the newer window.setImmediate). 基本上推迟执行代码直到发生超时处理(另请参见较新的window.setImmediate)。
  3. Execution of your function finishes. 执行您的功能完成。 Now, the browser has time for other things and will render the page. 现在,浏览器有时间处理其他事情并将呈现页面。 The rendering will trigger a scroll event, but because your function was deferred, it has not yet been added and thus nothing captures the scroll event. 渲染将触发滚动事件,但由于您的函数已延迟,因此尚未添加,因此没有捕获滚动事件。
  4. Rendering the page finishes. 渲染页面完成。 Now, the browser has time for other things and will execute the function set by setTimeout. 现在,浏览器有时间处理其他事情,并将执行setTimeout设置的功能。 This will add the onscroll event handler, but since the scroll event has already been triggered, the event handler will not be called. 这将添加onscroll事件处理程序,但由于已经触发了scroll事件,因此不会调用事件处理程序。

More information on the subject can be found here and here . 有关该主题的更多信息可以在这里这里找到。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM