滚动事件持续多长时间

how much time does a scroll event last?

本文关键字:长时间 事件 滚动      更新时间:2023-09-26

我遇到了一个由滚动事件引起的问题,这个问题可以重现如下:

  1. 将焦点设置为默认情况下在浏览器窗口中看不到的元素(需要滚动才能看到)。

  2. 然后附加一个监听器来捕获滚动事件。

我困惑的是,当我将焦点设置在未看到的元素上时,它会触发滚动事件,侦听器如何捕捉稍后附加的滚动事件?我想滚动事件可能会持续一段时间,但会持续多久?有人能给我一个建议吗?

这里有一个简单的代码来复制它:

<html>
<head>
<script type="text/javascript">
   var onchange = function(){
       var ip1 = document.getElementById("target");
       var ip2 = document.getElementById("source");
       var parent = document.getElementById("parent");
       ip2.focus();
       document.onscroll = function(e){
          console.log("scroll");
       };
   }
</script>
</head>
<body onload="onchange()">
<input id="target"></input>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<div id="parent">
 <input id="source">
</div>

对此的解释是JavaScript事件处理程序不会立即启动。因此,当您调用focus()时,它不会立即关注第二个文本框。相反,它执行onchange函数的其余部分,然后滚动页面。当页面滚动时,scroll事件的事件处理程序已经设置好。

原因如下:当事件在JavaScript中发生时,它会被放置在消息队列(JavaScript运行时引擎的内部组件)中。消息将从该队列中删除,并在事件循环的每个"回合"中进行处理。事件循环匝之间的时间量各不相同,但通常每匝不超过4ms。

为了解决您的问题,您可以在事件循环的下一轮中设置绑定(在scroll事件触发之后)。为了做到这一点,开发人员通常会做一些类似的事情:

setTimeout(function () {
    document.onscroll = function (e) {
        console.log("scroll");
    };
}, 0);

尽管我指定了0毫秒的延迟,但setTimeout回调直到事件循环的下一轮才会启动,所以它确实发生在大约4毫秒之后。您可以保证在处理完focus事件之后才会设置绑定(focus消息总是在setTimeout消息添加到消息队列之前添加到消息排队中,并且队列中的消息按顺序处理)。

有人提议在JavaScript中引入setImmediate函数,以便开发人员在下一轮事件循环中执行代码,但似乎不太可能在全球范围内采用该函数。请参阅:https://developer.mozilla.org/en-US/docs/Web/API/Window.setImmediate

该功能将类似于上面的破解:

setImmediate(function () {
    document.onscroll = function (e) {
        console.log("scroll");
    };
});

如果您感兴趣,setImmediate的一些polyfill比setTimeout破解更快,并且使用HTML5postMessage API。请参阅:https://github.com/YuzuJS/setImmediate

下面是一个固定代码的JSBin,它与损坏的代码一起运行:http://jsbin.com/laculukaqidu/1/edit?js,控制台,输出