【问题标题】:Can't stop scroll event from firing too many times无法阻止滚动事件触发太多次
【发布时间】:2020-08-06 16:23:06
【问题描述】:

所以我一直在阅读这个问题,并看到了很多不同的解决方案。目前我的代码如下所示:

我正在使用这个插件:http://benalman.com/projects/jquery-throttle-debounce-plugin/

// Bind throttled scroll event to load new items when page is scrolled to the bottom.
$(window).data('loading', false).scroll($.throttle(800, Olemas.ScrollLoad));

Olemas.ScrollLoad = function()  {
  if ($(window).data('loading') == true) return;
  if ($(window).scrollTop() >= ($(document).height() - $(window).height())) {
      if (Olemas.NextPage <= Olemas.MaxPage) {
          $(window).unbind('scroll'); // I have tried unbinding the event to stop it from launching
          Olemas.LoadMoreItems(Olemas.DivToUpdate); // load the new items
          $(window).data('loading', false).scroll($.throttle(800, Olemas.ScrollLoad)); // rebind scroll event.
      }

  }
};

问题是即使事件每 800 毫秒触发一次。当我快速滚动到底部时,滚动事件触发次数过多,页面加载错误。

if ($(window).scrollTop() >= ($(document).height() - $(window).height()))

在我的项目加载到页面后,此语句不应该通过,但在意识到页面高度已更改之前,它仍会通过几次。是否有可能是高度属性更新不够快,或者滚动事件已经以某种方式加载到 DOM 中?

在 LoadMoreItems 函数扩展页面后,如何阻止滚动事件触发。

编辑。

所以在这个函数中,警报会运行 2 次,然后在 LoadMoreItems ajax 成功中出现警报。

Olemas.ScrollLoad = function()  {
/// <summary>
/// Loads more items when scrolled to the bottom.
/// </summary>
if ($(window).data('loading') == true) return;
if ($(window).scrollTop() >= ($(document).height() - $(window).height())) {
    if (Olemas.NextPage <= Olemas.MaxPage) {
        alert(Olemas.NextPage); // This runs 2 times, before the LoadMoreItems changes the NextPage value
        $(window).off('scroll', $.throttle(800, Olemas.ScrollLoad));

        Olemas.LoadMoreItems(Olemas.DivToUpdate);
        $(window).data('loading', false).on('scroll', $.throttle(800, Olemas.ScrollLoad)); // rebind scroll event.
    }

}
};

Olemas.LoadMoreItems = function () {
  $(window).data('loading', true);
  $.ajax({
      url: Olemas.ActionLink,
      data: { "page": Olemas.NextPage, "facId": Olemas.FacultyId },
      success: function (data) {
          $(".loadingImage").hide();
          $(data).appendTo(Olemas.DivToUpdate);
          alert("Done") // This is run after the previous alerts have fired 2 times.
          Olemas.NextPage++;
          Olemas.CheckPages();
      }
  });
  return false;

};

【问题讨论】:

    标签: jquery jquery-plugins jquery-pagination


    【解决方案1】:

    好的,我的问题如下:

    // Bind throttled scroll event to load new items when page is scrolled to the bottom.
    $(window).data('loading', false).scroll($.throttle(800, Olemas.ScrollLoad));
    
    Olemas.ScrollLoad = function()  {
      if ($(window).data('loading') == true) return;
      if ($(window).scrollTop() >= ($(document).height() - $(window).height())) {
       if (Olemas.NextPage <= Olemas.MaxPage) {
          $(window).unbind('scroll'); // I have tried unbinding the event to stop it from launching
          Olemas.LoadMoreItems(Olemas.DivToUpdate); // load the new items
          $(window).data('loading', false).scroll($.throttle(800, Olemas.ScrollLoad)); // rebind scroll event.
          //The LoadMoreItems was an AJAX method and the rebinding was made before the ajax call had succeeded. 
          //That is why it fired the scroll event too many times.
      }
    
    }
    };
    

    我通过将加载布尔检查移到 LoadMoreItems 方法中解决了这个问题,这样该方法必须在重新绑定滚动之前完成。

    【讨论】:

      【解决方案2】:

      您可以随时尝试使用 on() / off()

      $(window).data('loading', false).on('scroll', doScroll);
      
      Olemas.ScrollLoad = function() {
          if ($(window).data('loading') == true) return;
          if ($(window).scrollTop() >= ($(document).height() - $(window).height())) {
              if (Olemas.NextPage <= Olemas.MaxPage) {
                  $(window).off('scroll', doScroll);
                  Olemas.LoadMoreItems(Olemas.DivToUpdate); // load the new items
                  $(window).data('loading', false).on('scroll', doScroll);
              }
          }
      };
      
      function doScroll() {
          $.throttle(800, Olemas.ScrollLoad);
      }​
      

      编辑:

      你不能这样做:

      $(window).on('scroll', $.throttle(800, Olemas.ScrollLoad));
      

      必须是:

      $(window).on('scroll', function() {
          $.throttle(800, Olemas.ScrollLoad));
      });
      

      或者简单地说:

      $(window).on('scroll', doScroll);
      
      function doScroll() {
          $.throttle(800, Olemas.ScrollLoad);
      }​
      

      调用一个单独的函数!

      使用单独函数的最后一个选项可以更轻松地使用 off() 取消绑定该函数,或者您可以通过以下方式取消绑定任何函数:

      $(window).off('scroll');
      

      【讨论】:

      • 感谢您的建议,我认为它使我更接近答案。在 if (Olemas.NextPage
      • 那是因为你调用了$.throttle(800, Olemas.ScrollLoad) 函数两次,并且没有将它附加到任何东西上。将函数传递给处理程序时,您不能使用括号和选项,那么您将需要一个单独的函数调用,因此在我的示例中使用单独的函数 doScroll,这是该答案中最重要的事情?
      • 如果我使用$(window).on('scroll', function () { $.throttle(800, Olemas.ScrollLoad); });,滚动事件永远不会触发。
      • 这完全取决于实际滚动的元素是窗口、正文还是其他元素。您必须绑定到正在滚动的元素,并且还有一些浏览器不一致。试试这个fiddle 看看事件触发...
      • 我不明白为什么 ScrollLoad 方法在没有括号的情况下不起作用。我必须以某种方式更改功能吗? Javascript 函数让我头疼。
      【解决方案3】:

      这是我的时间戳和时间间隔的解决方案。滚动功能完成后最后一次触发事件需要间隔。出于性能原因,我将延迟设置为 50。此示例每 2 秒触发一次该函数,享受自定义乐趣。

          var interval, timestamp = Date.now(),
      
          scrollFunction = function() {
              console.log('fire');
          },
      
          scrollHandler = function() {
              if(!interval) {
                  interval = setInterval(() => {
                      if((Date.now() - timestamp) > 2000) {
                          timestamp = Date.now();
                          scrollFunction();
                          clearInterval(interval);
                          interval = undefined;
                      }
                  }, 50);
              }
          }
      
      window.addEventListener('scroll', scrollHandler);
      scrollHandler();
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2013-09-23
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-03-25
        • 2021-04-22
        • 1970-01-01
        相关资源
        最近更新 更多