Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/jquery/70.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 侦听页面上的所有滚动事件_Javascript_Jquery - Fatal编程技术网

Javascript 侦听页面上的所有滚动事件

Javascript 侦听页面上的所有滚动事件,javascript,jquery,Javascript,Jquery,背景: 我正在编写一个组件,它在单击时打开一个子菜单。我不知道此组件将放置在页面上的何处,也不知道它将嵌套在可能设置了overflow属性的区域中多远 考虑到溢出可能会剪裁子菜单,我将子菜单本身附加到主体,给它一个绝对位置,并通过代码将其链接到原始组件。这将解决溢出问题 问题: 但是,如果用户滚动子菜单,子菜单将保持不变,而不是与其链接的组件一起移动,因此,我需要能够听到页面上发生的任何和所有滚动事件,以便能够适当地重新定位子菜单 如果有一个简单的方法来听所有的滚动事件,或者如果有另一个更好的方

背景:

我正在编写一个组件,它在单击时打开一个子菜单。我不知道此组件将放置在页面上的何处,也不知道它将嵌套在可能设置了
overflow
属性的区域中多远

考虑到溢出可能会剪裁子菜单,我将子菜单本身附加到
主体
,给它一个绝对位置,并通过代码将其链接到原始组件。这将解决溢出问题

问题:

但是,如果用户滚动子菜单,子菜单将保持不变,而不是与其链接的组件一起移动,因此,我需要能够听到页面上发生的任何和所有滚动事件,以便能够适当地重新定位子菜单

如果有一个简单的方法来听所有的滚动事件,或者如果有另一个更好的方法来做这个组件,我将感谢任何输入

我已经和JSFIDLE打过交道,建立了一个解决方案,但我没有取得任何成功,也没有在这个网站或其他任何地方找到关于这个问题的答案;虽然我可能使用了错误的搜索词,但我无法想象我是第一个提出这个问题的人

编辑

为了解决投票结果不一致的问题,我不是在不提供代码的情况下请求帮助调试问题,也不是在请求将来对任何人都没有帮助的东西。我想问的是,我将如何去倾听所有特定类型的事件,而不管事件发生在何处,我发现这是全球适用的,尽管这可能是主观的

编辑

$(窗口).on('scroll',function(){/**/})
不是选项,因为它只侦听窗口滚动,而不侦听任何嵌套滚动


$('#ex1#ex2')。on('scroll',function(){/**/})不是一个选项,因为它要求执行代码的人员知道页面上可能滚动的任何当前或未来区域。

您需要查看滚动是发生在窗口级别还是发生在元素级别。通常情况下,“*”就足够了

$('*').scroll(function() {
    alert('scroll');
});

下面是更新的链接:

如何列出所有元素和窗口

$('*').add(window).scroll(function() {
    console.log('scroll');
});

最好的方法是找出哪些元素是可滚动的,然后将侦听器附加到这些元素上。您可以在任何页面更改上运行此功能,以确保始终拥有所有滚动条

在性能方面,这比在每个元素上使用监听器(就像其他解决方案一样)都有好处:每次页面更新时,监听器都会更新。对于lots,这会迅速影响性能和内存使用

更新的小提琴:

守则:

$("*").each(function() {
    if($(this).css("overflow") == "auto" || $(this).css("overflow") == "scroll") {
        $(this).scroll(function() {
            console.log("scroll");
        });
    }
});
(感谢@pebbl的帮助)

然后,您可以将其包装到函数中,并在发生更改时运行它:

function addListeners() {
    $("*").each(function() {
        if($(this).css("overflow") == "auto" || $(this).css("overflow") == "scroll") {
            $(this).css('border', '1px solid red').scroll(function() {
                console.log("scroll");
            });
        }
    });
}

$("body").on("change",function()
    addListeners();
}

诚然,它有点复杂,但它通过尽可能少的事件侦听器解决了这个问题。

您应该能够使用第三个参数
true
附加文档级侦听器,以捕获所有元素上的滚动事件。下面是它的样子:

document.addEventListener('scroll', function(e){ }, true);
末尾的
true
是重要的部分,它告诉浏览器在发送时捕获事件,即使该事件通常不会冒泡,如更改、聚焦和滚动


这里有一个例子:

请在问题中发布相关代码。链接到小提琴是不够的。你可能会发现你可以用CSS来做,而不是用JS来乱搞定位。只需将滚动事件直接绑定到应用了
溢出:滚动
样式的父级即可。@Popleak,没有真正相关的代码,因为我不确定它会是什么——这是我的问题。JSFiddle提供了一种视觉效果,可以更好地理解页面可能存在的嵌套溢出。@Johannes~ Joe说的是监听目标滚动事件的最佳方式,并且不需要实现者知道任何事情。您只需要对子菜单进行编码,以便在它被放置/捕捉到另一个元素时重新绑定/删除它的事件。您的小部件只需要提供一个API调用,以允许将其移动到另一个元素。您的方法没有达到预期效果。它实际上是将滚动侦听器绑定到页面上的每个元素;再检查一遍。例如,只有可滚动元素有侦听器,而不是所有的
都有侦听器。您可以使用条件if语句进行筛选,但这不是用作
.scroll()
上下文的内容。检查这个,你就会看到。基本上,
$(this).add()
构造没有任何意义(),并且您过滤的内容将永远不会回到原始的
$().scroll()
。您最好将您所拥有的作为
.filter()
调用的一部分使用。请允许我将您带回我在注释中的第二个更新提琴作为证据。它将事件侦听器和listed=true属性应用于与选择匹配的每个元素;在dev工具中检查这些时,很明显,只选择了可滚动的元素。不管它在语法上是否正确,它都会按照我说的那样做。抱歉,但它不会-请参阅下面的小提琴版本,它确实有效(我添加了边框,以清晰地显示所选内容)。正如我所说,你的过滤器很好,是的,你在那里应用了你的属性(因此它们看起来很有效),但是你实际上是在将
.scroll()
应用到
$($('*'))
而不是过滤的元素,这就是为什么我将
.scroll()
放在过滤的部分中。如果您查看我之前的小提琴,您将看到将属性向下移动到您正在应用的位置
.scroll()
,这意味着每个元素都应用了属性。我希望我能将此答案向上投票100次,谢谢!我已经更新了示例以演示多个/嵌套区域,并简化了控制台日志