jQuery滚动事件每次滚动只触发一次

4
我有一些jQuery代码来检查我是否已经滚动到了窗口底部。
$(window).scroll(function(){
    if($(window).scrollTop() + $(window).height() == $(document).height()) {
        appendToGrid();
    }
})

我的appendToGrid()函数会将用户滚动到页面顶部并添加内容。问题是,我需要每次滚动调用该函数一次。现在,它在每次滚动时被多次调用。 如果我改为:
$(window).one('scroll',function() {
    if($(window).scrollTop() + $(window).height() == $(document).height()) {
        appendToGrid();
    }
});

该事件只会触发一次,但我需要它每次滚动时都触发,以便用户可以向下滚动并不断返回页面顶部。

我也尝试了以下方法,但它仍然会多次触发。

var fired = false;
$(window).scroll(function(){
    if($(window).scrollTop() + $(window).height() == $(document).height() && !fired) {
        fired = true;
        appendToGrid();
        fired = false;
    }
})
2个回答

8

一旦调用appendToGrid,您可以添加一个冷却计时器。这类似于您的fired标志,但只有在等待2000ms后才会重置。您可以根据需要调整该时间。

var recentScroll = false;
$(window).on('scroll',function() {
    if(!recentScroll && $(window).scrollTop() + $(window).height() == $(document).height()) {
        appendToGrid();
        recentScroll = true;
        window.setTimeout(() => { recentScroll = false; }, 2000)
    }
});

只是好奇,因为你正在设置超时,这个会阻塞主线程吗? - Matthew Zackschewski
不,超时并不会阻塞主线程,它不像其他语言中的休眠那样暂停所有执行 - 它将继续执行其他事情,直到等待2000毫秒结束。 - IrkenInvader
谢谢您的快速回复和提供信息。这很有用! - Matthew Zackschewski

6
另一种选择是对逻辑进行节流,只有在用户停止操作一段时间后才会发生。

$(function(){
  //cache common variables so they are created once
  var $window = $(window);
  var $document = $(document);
  var debounce;
  
  $window.on('scroll', function(){
    //clear the delay if it's not finished yet
    if (debounce) clearTimeout(debounce);
    
    //start a new delay
    debounce = setTimeout(function(){
      //remove reference so another delay can start
      debounce = null;
      //perform whatever logic you normally would do
      if($window.scrollTop() + $window.height() == $document.height()) {
        appendToGrid();
      }
    }, 300);
  });
});


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接