检查用户是否已滚动到底部

IT技术 javascript jquery scroll pagination
2021-02-02 07:41:12

我正在制作一个分页系统(有点像 Facebook),当用户滚动到底部时会加载内容。我想最好的方法是找到用户何时位于页面底部并运行 Ajax 查询以加载更多帖子。

唯一的问题是我不知道如何检查用户是否已滚动到页面底部。有任何想法吗?

我正在使用 jQuery,因此请随时提供使用它的答案。

6个回答

.scroll()使用事件window,如下所示:

$(window).scroll(function() {
   if($(window).scrollTop() + $(window).height() == $(document).height()) {
       alert("bottom!");
   }
});

你可以在这里测试,这需要窗口的顶部滚动,所以它向下滚动了多少,添加可见窗口的高度并检查它是否等于整体内容的高度 ( document)。如果你想检查用户是否靠近底部,它看起来像这样:

$(window).scroll(function() {
   if($(window).scrollTop() + $(window).height() > $(document).height() - 100) {
       alert("near bottom!");
   }
});

您可以在此处测试该版本,只需将其调整100为您想要触发的底部像素即可。

@KevinVella Vella 很好的组合是在下划线实用程序中将其与 _.debounce() 一起使用,以防止在用户停止滚动之前触发它 - underscorejs.org/#debounce -
2021-03-14 07:41:12
Firefox 调用 alert("bottom!"); 很多次(适用于 chrome 和 safari)
2021-03-22 07:41:12
这有点问题,如果你做一个console.log()而不是警报它有时会重复命令。
2021-03-25 07:41:12
@NickCraver 是否有可用的纯 js 实现?
2021-03-26 07:41:12
像往常一样,你比我先到那里。无论如何,对于 OP,如果您有一个帖子容器,请使用它的 ID 而不是“窗口”,此外,您可能希望将最后一个 .height() 更改为 scrollHeight
2021-03-27 07:41:12

我不确定为什么这还没有发布,但根据MDN 的文档,最简单的方法是使用本机 javascript 属性:

element.scrollHeight - element.scrollTop === element.clientHeight

当您位于任何可滚动元素的底部时返回 true。所以只需使用javascript:

element.addEventListener('scroll', function(event)
{
    var element = event.target;
    if (element.scrollHeight - element.scrollTop === element.clientHeight)
    {
        console.log('scrolled');
    }
});

scrollHeight在浏览器中得到广泛支持,从 ie 8 到更精确,而clientHeightscrollTop都受到所有人的支持。即使 ie 6。这应该是跨浏览器安全的。

Math.abs(element.scrollHeight - element.scrollTop - element.clientHeight) <= 3.0(用您认为适合您情况的任何像素容差替换 3.0)。这是要走的路,因为 (A) clientHeight, scrollTop, 和clientHeight都是四舍五入的,如果全部对齐,可能会导致 3px 错误,(B) 用户几乎看不到 3 像素,因此用户可能会认为您的网站有问题当他们“认为”他们在页面底部时,实际上他们不在页面底部,并且 (C) 某些设备(尤其是无鼠标设备)在滚动时可能会出现奇怪的行为。
2021-03-11 07:41:12
我想补充一点,它有可能返回假阴性,因为一侧可能返回一个小数,而另一侧返回一个整数(例如200.181819304947200)。我添加了一个Math.floor()来帮助解决这个问题,但我不知道这有多可靠。
2021-03-16 07:41:12
我在 <body> 元素上试过这个,当浏览器滚动到顶部而不是底部时会触发。
2021-04-02 07:41:12
对我来说,这不适用于跨浏览器。与 Firefox 相比,我在 chrome 上得到了完全不同的结果。
2021-04-05 07:41:12
请注意,在某些情况下,情况可能并非如此。Firefox 47 报告 textarea clientHeight 为 239,而上面的公式在滚动到底部时给出 253。也许填充/边框或其他东西正在影响它?无论哪种方式,添加一些摆动空间都不会受到伤害,例如var isAtBottom = ( logField.scrollHeight - logField.scrollTop <= logField.clientHeight + 50 );. 这对于自动滚动字段只有在已经在底部时才有用(因此用户可以手动检查实时日志的特定部分而不会丢失它们的位置等)。
2021-04-08 07:41:12

Nick Craver 的回答工作正常,避免了值$(document).height()因浏览器而异的问题

要使其适用于所有浏览器,请使用James Padolsey 的此功能

function getDocHeight() {
    var D = document;
    return Math.max(
        D.body.scrollHeight, D.documentElement.scrollHeight,
        D.body.offsetHeight, D.documentElement.offsetHeight,
        D.body.clientHeight, D.documentElement.clientHeight
    );
}

代替$(document).height(),所以最终的代码是:

$(window).scroll(function() {
       if($(window).scrollTop() + $(window).height() == getDocHeight()) {
           alert("bottom!");
       }
   });
他更新了一个稍微压缩的版本函数 getDocHeight() { var D = document; return Math.max( D.body.scrollHeight, D.documentElement.scrollHeight, D.body.offsetHeight, D.documentElement.offsetHeight, D.body.clientHeight, D.documentElement.clientHeight ); }
2021-03-13 07:41:12
使用min而不是可能更好max,尤其是在有边距的情况下,以避免意外阻止用户滚动到您认为是页面底部的位置。
2021-03-18 07:41:12
当我到达顶部而不是底部(Chrome)时会提醒我。
2021-03-30 07:41:12

对于那些使用尼克的解决方案并获得重复警报/事件触发的人,您可以在警报示例上方添加一行代码:

$(window).scroll(function() {
   if($(window).scrollTop() + $(window).height() > $(document).height() - 100) {
       $(window).unbind('scroll');
       alert("near bottom!");
   }
});

这意味着代码只会在您第一次到达文档底部 100 像素以内时触发。如果您向上滚动然后向下滚动,它就不会重复,这可能有用也可能没有用,具体取决于您使用 Nick 代码的目的。

$(document).height() - 100 是关键,我最终也将其更改为 50。出于某种原因,有时添加浏览器扩展或防病毒软件会更改屏幕的值,因此最好也只是为延迟加载工作留一点余量。
2021-03-11 07:41:12
前几天我遇到了这种类型的问题。我在页面滚动时使用 ajax 调用。当我连续滚动页面时,请求发送到服务器。阅读您的这个答案后,我明白使用$(window).unbind('scroll');线路问题将得到解决。
2021-03-15 07:41:12
如何选择特定的 div id 而不是整个窗口?
2021-03-20 07:41:12
在第一个之外,如果您可以放置​​一个不同的,如果它测试您希望脚本进行的更改是否存在,例如已将一个类应用于 div。如果它已经运行,这将使第二个嵌套 if not run。
2021-03-22 07:41:12

除了 Nick Craver 出色的公认答案之外,您还可以限制滚动事件,使其不会被频繁触发,从而提高浏览器性能

var _throttleTimer = null;
var _throttleDelay = 100;
var $window = $(window);
var $document = $(document);

$document.ready(function () {

    $window
        .off('scroll', ScrollHandler)
        .on('scroll', ScrollHandler);

});

function ScrollHandler(e) {
    //throttle event:
    clearTimeout(_throttleTimer);
    _throttleTimer = setTimeout(function () {
        console.log('scroll');

        //do work
        if ($window.scrollTop() + $window.height() > $document.height() - 100) {
            alert("near bottom!");
        }

    }, _throttleDelay);
}
什么?调用机器负载以防止简单计算?我根本看不出这有什么效率
2021-03-10 07:41:12
也许这只是我,它可以使用一些基准测试,但我不喜欢在每个滚动事件上调用 clearTimeout 和 setTimeout 的想法。我会发出 1 setTimeout 并在该处理程序中添加一些守卫。这可能只是一个微优化(如果有的话)。
2021-03-17 07:41:12
可能应该指出,这需要 Underscore.js: underscorejs.org不过,这是一个很好的观点。滚动事件应该几乎总是被限制以避免严重的性能问题。
2021-04-03 07:41:12
这是一个非常巧妙的补充!我可以想到进一步的改进。目前,如果用户继续滚动,检查高度的功能将不会运行。如果这是一个问题(例如,您想在用户向下滚动一半时触发该函数,而不管他们是否继续滚动),您可以轻松确保该函数实际被调用,同时仍然禁止在所选间隔内进行多次调用。这是展示它的要点。gist.github.com/datacarl/7029558
2021-04-03 07:41:12