【问题标题】:How to lazy render large dataset based on scroll events?如何基于滚动事件延迟渲染大型数据集?
【发布时间】:2020-11-20 16:51:48
【问题描述】:

我有一个很大的dataset,想知道如何延迟渲染dataset?我能够在视口中呈现数据。当用户滚动页面时如何呈现剩余的数据?

到目前为止,在我的自定义绑定中,我这样做是为了加快我的初始页面加载速度。

var elementRelativeHeight = $element.offset().top;
var windowHeight = $(window).height();

if(elementRelativeHeight > windowHeight) {
    //How do I register a callback so it template is rendered upon scroll?
} else {
    $("#mydiv").appendChild($element);
}

【问题讨论】:

  • 网上有很多关于延迟加载的例子。解决方案实际上取决于数据是什么以及您需要如何获取它。
  • 我更新了我的问题的标题。我对延迟渲染很熟悉,但不知道如何根据滚动事件来实现。
  • 您可以添加一个事件侦听器并获取用户与屏幕底部的距离。如果它们接近,则延迟加载另一个数据包
  • 我正在努力写那篇文章。如果你想给我看一个很好的例子。

标签: javascript jquery


【解决方案1】:

在处理要显示的大块数据时,重要的是要记住,实际上一次显示 1000 个项目实际上是没有意义的,因为如果项目高度为 50px 而您的视口高度为 1000px那么您将只能看到 20 个项目,其余项目被隐藏。那么为什么不在滚动列表时通过加载更多数据来慢慢显示这些数据。

这里是这个想法的一个完整例子。通过在向下滚动时通过计算屏幕外有多少项目来加载更多数据,如果计数小于 5 意味着您剩下的项目很少,因此可以安全地添加更多项目。这也将增加一种无缝的体验,因此用户永远不会碰到边缘,除非什么都没有了

$(document).ready(function() {
  var data = [];
  /* How many items we load each iteration */
  var displayLimit = 30;
  var sensitivity = 300;
  var scrollTimeout = false;
  /* Keep track on the items being displayed */
  var displayData = [];

  for (var i = 0; i < 1000; i++) {
    data.push("Item - " + i);
  }

  var loadData = function() {

    /* [0] means using the javascript object than jquery.
       It is very important not to use $() in a loop, unless its
       absolutely necessary. Since this will cause severe performance
       issue later on. If it can be placed outside then put it outside.
     */
    var container = $(".items")[0]

    for (var i = 0; i < displayLimit; i++) {
      /* If the length is 20 means, index 0 to 19 are displayed
         and start at 20th index of the original data source
       */
      var currentIndex = displayData.length;

      /* check if it's not out of bounds */
      if (currentIndex > data.length) {
        break;
      }

      var item = data[currentIndex];

      displayData.push(item);

      var element = document.createElement("div");
      element.classList.add("item");
      element.innerHTML = item;

      container.appendChild(element);
    }
  };

  /* Load data at the beginning */
  loadData();

  $(".scrollable").scroll(function(event) {
    var edge = false;
    /* Height of the scrollable container */
    var height = $(event.target).height();
    /* Refers to how much you have scrolled */
    var scrollY = $(event.target).scrollTop();
    /* Amount of pixels of scrollable content */
    var scrollHeight = event.target.scrollHeight;

    /* If we happen to hit the edge but the timeout
       is still in effect, call the function regardless
     */
    if (height + scrollY == scrollHeight) {
      edge = true;
    }

    if (!scrollTimeout ||
      edge) {

      /* When dealing with loading while scrolling
       it is very important to limit how many times
       this event gets called. If this is not here,
       you will notice this callback gets called
       a `lot` of times. So we don't want this to cause
       a performance issue later on.
      */
      scrollTimeout = true;
      setTimeout(function() {
        scrollTimeout = false;
      }, sensitivity);

      var count = 0;
      var toScroll = toScroll;
      var items = $(".items .item");

      /* Count how many items are outside the screen */
      for (var i = 0; i < items.length; i++) {
        var item = items[i];
        /* Refers to Y position of the element
           on your screen */
        var Y = $(item).offset().top;
        /* Since we're getting the items outside the
           screen we have to get the items that `are`
           outside the height of the screen +
           the scrolled amount */
        var currentY = height + scrollY;

        /* Check if this item is outside */
        if (Y > currentY) {
          count++;
        }

        /* There's no point to count anymore 
           if we wanted to loadMore() when there are
           5 items left to scroll */
        if (count > toScroll) {
          break;
        }
      }

      /* If there are 5 or less items to scroll
         loadMore() data
       */
      if (count <= 5) {
        loadData();
      }
    }
  });
});
.item {
  margin-bottom: 20px;
  border: 1px solid black;
  text-align: center;
}

.scrollable {
  height: 600px;
  overflow: auto;
}

body {
  overflow: hidden;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="scrollable">
  <div class="items">

  </div>
</div>

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-07-07
    • 2019-02-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-08-28
    • 1970-01-01
    相关资源
    最近更新 更多