【问题标题】:How to do infinite scrolling with javascript only without jquery如何在没有 jquery 的情况下仅使用 javascript 进行无限滚动
【发布时间】:2014-04-11 15:53:31
【问题描述】:

我想用javascript实现无限滚动,不用jquery。

我是 JavaScript 新手。

在网上搜索了一遍,我有这个代码。

<!DOCTYPE html><html lang="en"><head><title>scrolling</title>
<style>
.page {height: 900px;border:solid 1px #ccc}
</style>
</head>
<body>

<div id="scrollcontent">

<div class="page"></div>

</div>

<script>

//########################
function getScrollXY() {
var scrOfX = 0, scrOfY = 0;
if( typeof( window.pageYOffset ) == 'number' ) {
    //Netscape compliant
    scrOfY = window.pageYOffset;
    scrOfX = window.pageXOffset;
} else if( document.body && ( document.body.scrollLeft || document.body.scrollTop ) ) {
    //DOM compliant
    scrOfY = document.body.scrollTop;
    scrOfX = document.body.scrollLeft;
} else if( document.documentElement && ( document.documentElement.scrollLeft || document.documentElement.scrollTop ) ) {
    //IE6 standards compliant mode
    scrOfY = document.documentElement.scrollTop;
    scrOfX = document.documentElement.scrollLeft;
}
return [ scrOfX, scrOfY ];
}

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.addEventListener("scroll", function (event) {
if (getDocHeight() == getScrollXY()[1] + window.innerHeight) 
{ 
  var oldcontent = document.getElementById('scrollcontent');
  oldcontent.innerHTML = oldcontent.innerHTML + '<div class="page">new content loaded</div>';
  document.getElementById("scrollcontent").innerHTML=oldcontent.innerHTML;

}
});
</script>
</body>
</html>

但是,此代码仅在滚动条触及底部时才有效。

我希望它在用户距离底部 100 像素时工作。 (或接近底部)

我还需要代码在大多数现代浏览器、移动设备等中工作。

另外,有什么办法可以改进这段代码吗?请提出建议。

如果代码有任何错误,请更正。

谢谢

【问题讨论】:

    标签: javascript


    【解决方案1】:

    要实现该行为,您不需要JQueryJQuery plugin。您只需要Pure Css OR Css + Javascript,这取决于您要支持的百分比

    但是...不要使用onScroll:您可以使用Vanilla JavascriptIntersectionObserver API 完成所有这些操作。

    您需要做的就是放置元素并在它们出现在屏幕上时进行监听。您可以使用几行 javascript 和 html 行来完成此操作,它比在浏览器中监听滚动事件的性能要高得多

    我最近整理了一篇关于这个的文章check it here

    【讨论】:

      【解决方案2】:

      为什么要使用 jQuery?一些像 window.outerHeight 这样的原生属性实际上可能在某些浏览器上返回不准确的结果。 jQuery 修复了这个问题,因此您可以依赖您使用的方法在任何浏览器上返回相同的结果,并且速度足够快。

      这里有一个非常简单的方法来实现无限滚动而不会对性能产生任何影响:

      $(window).on('scroll', function() {
          var threshold = 120;
          if (window.pageYOffset > 0 && window.pageYOffset + $(window).outerHeight(false) >= $(document).outerHeight(false) - threshold) {
              // call your infinite scroll callback, like infiniteScrollDebounced($('#mytable'))
          }
      }).scroll();
      

      注意:if 子句中的条件是故意这样的,所以如果用户不滚动,它不会在 window.pageYOffset > 0 之后计算,也会进入 if(一些微优化;))。零可以用 20 或 100 代替,所以这是网站将尝试检查用户是否滚动并需要对其进行处理之后的阈值。

      我使用 debounce 来推迟加载数据的真正调用(通常是网站在无限滚动时加载数据),demo:https://davidwalsh.name/function-debounce

      所以我有这个方法:

      var infiniteScrollDebounced = _.debounce(function($table) {
          var params = $table.data('table-params');
          // Don't request any more if we have reached the end
          if (params.end)
              return;
      
          params.page++;
          params.append = true;
      
          GridHelper.reload($table, null, params);
      }, 100, true);
      

      我的表格附有数据以保存当前进度(页面、排序、过滤等),这些数据被检索并传递到查询中,因此我每次都能得到正确排序和过滤的结果。 GridHelper.reload() 函数处理请求并在数据到达时更新表的参数(新参数是响应的一部分)。

      【讨论】:

        【解决方案3】:

        我使用元素的scrollHeight、scrollTop 和clientHeight 属性来判断滚动是否到达底部。这是我的代码。希望对你有帮助。

        Click here for more information.

        Image describing scrollHeight, scrollTop and clientHeight.

        <html>
        <head>
        <title>Infinite Scroll</title>
        </head>
        <body>
          <h3>Infinite Scroll Example</h3>
          <div id="scrollContent" style="overflow-y: scroll; height: 100px; width: 500px">
            <div style="height: 300px; background-color: red">
            </div>
          <div>
        </body>
        
        <script type="text/javascript">
          document.addEventListener('DOMContentLoaded',function () {
            var elm = document.getElementById('scrollContent');
            elm.addEventListener('scroll',callFuntion);
        
            function callFuntion(){
              var scrollHeight = elm.scrollHeight;
              var scrollTop = elm.scrollTop;
              var clientHeight = elm.clientHeight;
        
              if(scrollHeight-scrollTop == clientHeight){
                elm.innerHTML += '<div style="height: 300px; background-color: blue"> New Element Added </div>' ;
              }
            }
        
          });
        </script>
        
        </html>

        【讨论】:

          【解决方案4】:

          我使用requestAnimationFrame 而不是监听滚动。我还添加了一个基于时间的节流阀,这样它就不会过度使用我们的页面并批量添加元素:

          var numElementsToAdd = 10,
              offsetForNewContent = 20;
          
          function checkInfiniteScroll(parentSelector, childSelector) {
            var lastDiv = document.querySelector(parentSelector + childSelector),
                lastDivOffset = lastDiv.offsetTop + lastDiv.clientHeight,
                pageOffset = window.pageYOffset + window.innerHeight;
          
            if(pageOffset > lastDivOffset - offsetForNewContent ) {
              for(var i = 0; i < numElementsToAdd; i++) {
                var newDiv = document.createElement("div");
                newDiv.innerHTML = "my awesome new div";
                document.querySelector(parentSelector).appendChild(newDiv);
              }
              checkInfiniteScroll(parentSelector, childSelector);
            }
          };
          
          var lastScrollTime = Date.now(), 
              checkInterval = 50;
          
          function update() {
            requestAnimationFrame(update);
          
            var currScrollTime = Date.now();
            if(lastScrollTime + checkInterval < currScrollTime) {
              checkInfiniteScroll("#scroll-content", "> div:last-child");
              lastScrollTime = currScrollTime;
            }
          };
          
          update();
            #scroll-content > div {
                background: #c0c0c0;
                height: 40px;
                margin-bottom: 5px;
            }
          <div id="scroll-content">
              <div>test div</div>
          </div>

          Demo

          【讨论】:

            【解决方案5】:

            首先,我认为您不必再​​支持 netscape 和 ie6。因此,考虑到这一点,我创建了以下脚本

            document.addEventListener("scroll", function (event) {
                checkForNewDiv();
            });
            
            var checkForNewDiv = function() {
                var lastDiv = document.querySelector("#scroll-content > div:last-child");
                var lastDivOffset = lastDiv.offsetTop + lastDiv.clientHeight;
                var pageOffset = window.pageYOffset + window.innerHeight;
            
                if(pageOffset > lastDivOffset - 20) {
                    var newDiv = document.createElement("div");
                    newDiv.innerHTML = "my awesome new div";
                    document.getElementById("scroll-content").appendChild(newDiv);
                    checkForNewDiv();
                }
            };
            

            另见jsfiddle

            【讨论】:

            • 太棒了。为什么这只有两个赞成票?有问题吗?一些我还看不到的可怕的不当行为?
            • 这很简单。我喜欢它。谢谢!
            • 当你可以只使用checkForNewDiv 时,为什么你有function (event) { checkForNewDiv(); }??
            【解决方案6】:

            如何替换这行代码:

            if (getDocHeight() == getScrollXY()[1] + window.innerHeight)
            

            以下内容:

            if (getDocHeight() - 20 <= getScrollXY()[1] + window.innerHeight) 
            

            其中20 是您希望触发器从底部开始执行多少pxs 的数字。

            Fiddle

            【讨论】:

            • 我在我的网站上试过这个,它触发了很多次事件,并且一次加载了许多页面。由于我上面给出的示例代码在 ajax 加载的 div 中没有内容,它可能正在正确加载,但是当 ajax 加载的 div 中有内容时,加载需要一些时间,同时,事件是多次触发。你能建议解决这个问题吗?谢谢。
            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2013-08-08
            • 2012-01-23
            • 1970-01-01
            • 2013-12-11
            • 2016-04-16
            • 1970-01-01
            相关资源
            最近更新 更多