jQuery scroll event fire once per scroll

2019-08-06 18:46发布

问题:

I have some jQuery code to check if I've scrolled to the bottom of the window.

$(window).scroll(function(){
    if($(window).scrollTop() + $(window).height() == $(document).height()) {
        appendToGrid();
    }
})

My appendToGrid() function scrolls the user to the top of the page and adds content. Problem is, I need this function called once per scroll. As I have it now, it is called multiple times per scroll.

If I change it to

$(window).one('scroll',function() {
    if($(window).scrollTop() + $(window).height() == $(document).height()) {
        appendToGrid();
    }
});

it will only fire once total, but I need it to fire once per scroll so the user can scroll to the bottom and keep getting sent back to the top of the page.

I've also tried the below but it still fires multiple times.

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

回答1:

You could add a cooldown timer once appendToGrid is called. This is similar to your fired flag but it only resets after a 2000ms wait. You can adjust that time to whatever feels best.

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


回答2:

Another option would be to throttle the logic so it only happens after the user stops the action for a period of time.

$(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);
  });
});