Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/date/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 如何在不将onscroll处理程序附加到每个容器的情况下捕获页面上的所有滚动事件_Javascript_Dom_Scroll_Dom Events - Fatal编程技术网

Javascript 如何在不将onscroll处理程序附加到每个容器的情况下捕获页面上的所有滚动事件

Javascript 如何在不将onscroll处理程序附加到每个容器的情况下捕获页面上的所有滚动事件,javascript,dom,scroll,dom-events,Javascript,Dom,Scroll,Dom Events,考虑以下网页: <html> <body onscroll="alert('body scroll event')"> <div style='width:200px;height:200px;overflow:auto' onscroll="alert('div scroll event')"> <div style='height:400px'> </div> </div

考虑以下网页:

 <html>
   <body onscroll="alert('body scroll event')">
     <div style='width:200px;height:200px;overflow:auto' onscroll="alert('div scroll event')">
       <div style='height:400px'>
       </div>
     </div>
   </body>
 </html>

这个html创建了一个带有滚动条的div。如果移动滚动条,将触发div元素上的
onscroll
事件。但是,不会触发主体上的
onscroll
事件。这是意料之中的,因为W3C声明元素
onscroll
事件不会“冒泡”

然而,我正在开发一个客户端web框架,它需要知道页面任何元素上的滚动条何时被滚动。如果
onscroll
冒泡,这将很容易做到,但不幸的是,它没有冒泡。是否有其他方法可以检测整个页面上的
onscroll
事件?(现在我主要关注Webkit,所以Webkit特定的解决方案就可以了…)

以下是我尝试过的一些事情:

  • 捕获
    DOMAttrModified
    (移动滚动条时似乎不会触发。)
  • 使用DOM观察器(对于滚动条似乎也不会触发)
  • onscroll
    事件类型更改为气泡(似乎不可能)
  • 似乎全局捕获
    onscroll
    事件的唯一方法是将
    onscroll
    事件附加到每个可能滚动的元素,这非常难看,会影响我的框架的性能

    有人知道更好的方法吗?

    *…蟋蟀唧唧叫*

    好吧,我想这个问题不会得到任何stackoverflow的喜爱,所以我不妨回答我自己的问题,以及我迄今为止找到的最佳解决方案,以防其他用户偶然发现这个问题:

    我提出的最佳解决方案是为BODY元素捕获“onmousedown”和“onkeydown”:这些事件会冒泡,因此如果用户试图移动页面上的滚动条,这些全局函数将作为副产品启动。然后,在这些函数中,只需查找event.target并将临时“onscroll”事件附加到这些对象,直到鼠标/键再次“向上”为止。使用该方法,您可以避免“处理程序膨胀”,并且仍然全局捕获所有“onscroll”事件。(我认为这也适用于“鼠标滚轮”滚动,但我对最终褶皱的研究仍在进行中。)

    我也有同样的问题

    当然,最简单的方法是使用jQuery请注意,此方法可能会显著降低页面速度。此外,它不会考虑在事件绑定后添加的任何新元素。

    $("*").scroll(function(e) {
        // Handle scroll event
    });
    
    在vanilla JavaScript中,您可以在
    addEventListener
    调用中将
    useCapture
    布尔值设置为
    true
    ,它将触发所有元素,包括动态添加的元素

    document.addEventListener('scroll', function(e) {
        // Handle scroll event
    }, true);
    
    但是请注意,这将在滚动事件实际发生之前触发。据我所知,事件经历了两个阶段。捕获阶段首先发生,从页面根(ownerDocument?)开始,向下遍历到事件发生的元素。在这之后是冒泡阶段,它从元素返回到根

    一些快速测试也表明jQuery可能就是这样处理的(至少用于跟踪所有页面元素上的滚动条),但我不是100%确定


    下面是一个JSFIDLE,展示了普通JavaScript方法

    在现代浏览器中检测所有滚动事件的最简单方法是在附加事件时使用“捕获”而不是“冒泡”:

    window.addEventListener('scroll', function(){ code goes here }, true)
    

    不幸的是,据我所知,在较旧的浏览器中没有类似的功能,例如当您想要关闭对话框时,以下功能可以正常工作,即在滚动背景中的任何内容后关闭对话框:

    var scrollListener = function(e) {
        // TODO: hide dialog
        document.removeEventListener('scroll', scrollListener, true);
    };
    
    document.addEventListener('scroll', scrollListener, true);
    

    此外,您还应该在document.nice中添加鼠标滚轮事件-我没有参与整个答案,但您一提到“onmousedown”,我就已经指出了正确的方向-谢谢Window.onscroll不起作用?请注意第一种方法,因为将事件监听器附加到每个DOM元素会使事情变得非常缓慢(更不用说,这并没有考虑在创建事件处理程序之后添加的元素)。第二种可能更可取,但如果可能的话,您也应该在不需要的时候删除它(例如,如果您只想让它知道何时关闭弹出窗口或其他东西,只在弹出窗口打开时附加它,并在弹出窗口关闭时删除它)。我试图找出哪个元素正在进行滚动(因此,在滚动处理程序因CSS更改而中断后,将其附加到)而第一个方法没有给我任何东西。结果是,它是
    文档本身,所以之前处理程序附加了“body”第二种方法帮助我发现确实是文档/窗口本身在滚动。非常感谢