无限滚动jQuery插件


72

我正在尝试用Coldfusion开发的网站上设置无限滚动,我是javascript和jquery的新手,所以我在解决所有这些问题时遇到了一些问题。为了使用无限滚动插件,我是否需要在网站上进行分页,或者有没有办法做到这一点?


@francis你的意思是昂贵的。您不必将所有内容都绑定到滚动条。这取决于要做什么。这是一个通用示例。滚动支持跨浏览器。
侯赛因

1
试试这个真棒无限滚动- github.com/yairEO/infinite
VSYNC

@vsync不会怪你,但是滚动时似乎有点问题,对我来说,滚动时从20跳到40?Moz Firefox fyi
Shaun Moore

@ShaunMoore-取决于操作系统以及是否启用了平滑滚动。我已经在6年前设计了它,用于具有隐藏滚动条的设计,然后这种行为更有意义
vsync

Answers:


136

为此,您不需要无限滚动插件。要检测滚动何时到达页面末尾,可以使用jQuery

$(window).scroll(function () { 
   if ($(window).scrollTop() >= $(document).height() - $(window).height() - 10) {
      //Add something at the end of the page
   }
});

JsFiddle上的演示


2
到底为什么是-10常数?它是滚动条中箭头的大小吗?
BrunoSalvino 2011年

8
@bruno Scroll在页面末尾到达10px而不是在页面末尾到达时发生。不一定需要它,但是它提供了更大的控制权来定义页面应滚动到的点。
侯赛因

3
是否可以将其用于固定DIV而不是页面?
Mark Vital 2012年

@Hussein谢谢,这很简单,很不错,我可以在上面的代码中调用我的ajax
神户,

好东西!我必须对较大的滚动区域触发器进行少量修改。基本上,我设置了一个触发器来阻止连续追加,直到最后一次追加成功为止。在这里回答:stackoverflow.com/a/18090897/337903
Nick

26

我正在使用侯赛因的答案与AJAX请求。我修改了代码,使其在300px而不是10px处触发,但是它开始导致我的追加在AJAX请求完成之前倍增,因为滚动调用在300px范围内触发的频率比在10px范围内触发的频率高得多。

为了解决这个问题,我添加了一个触发器,该触发器将在成功加载AJAX时翻转。我的代码看起来像这样:

var scrollLoad = true;

$(window).scroll(function () { 
  if (scrollLoad && $(window).scrollTop() >= $(document).height() - $(window).height() - 300) {
    scrollLoad = false;
    //Add something at the end of the page
  }
});

然后在我的AJAX响应中,将设置scrollLoadtrue


我还必须添加分页代码来完成效果。不难,但要注意一点。
thekingoftruth 2013年

我用这种方法。它的作品很好。谢谢。但是在页面末尾会出现闪烁。这是数据库的最后一条记录。但是,当用户尝试加载更多内容时,页面就会闪烁。如何克服呢?
Prageeth Liyanage,


2
$(function(){ 
    $(window).scroll(function(){
           if($(document).height()<=$(window).scrollTop()+$(window).height()+100){
               alert('end of page');
           }
       });
});

有人要求解释,所以这里是解释

$(document).height()->是整个文档的高度,在大多数情况下,它等于当前文档的元素。

$(window).height()->是窗口的高度(浏览器)是指您在浏览器中看到的任何内容的高度。

$(window).scrollTop()-> Element.scrollTop属性获取或设置元素内容向上滚动的像素数。元素的scrollTop是元素顶部到其最顶部可见内容的距离的度量。当元素内容未生成垂直滚动条时,则其scrollTop值默认为0。

$(document).height()<=$(window).scrollTop()+$(window).height()+100

现在,将$(window).scrollTop()与$(window).height()相加,检查结果是否等于您的documnet高度。如果相等,则表示您到达了end.we。我们也要加上100,因为我想检查距文件底部100像素之前的像素(请注意<=条件)

如果我错了请指正我


1
尽管此答案可能是正确且有用的,但如果您在其中包含一些解释以说明它如何帮助解决问题,则最好使用该答案。如果发生更改(可能不相关)导致它停止工作,并且用户需要了解它曾经如何工作,那么这在将来特别有用。谢谢!
Hatchet

1

如果您有一个可滚动元素,例如具有滚动溢出的div,但没有可滚动文档/页面,则可以采用这种方式。

       $(function () {
            var s = $(".your-scrollable-element");
            var list = $("#your-table-list");

            /* On element scroll */
            s.scroll(function () {
                /* The scroll top plus element height equals to table height */
                if ((s.scrollTop() + s.height()) == list.height()) {
                    /* you code */
                }
            });
        });

1

我遇到了同样的问题,但是找不到适合我的插件。所以我写了下面的代码。此代码通过使用ajax和分页获取数据将模板附加到元素。为了检测用户何时滚动到div的底部,我使用了以下条件:

var t = $("#infiniteContent").offset().top;
var h = $("#infiniteContent").height();
var ws = $(window).scrollTop();
var dh = $(document).height();
var wh = $(window).height();

if (dh - (wh + ws) < dh - (h + t)) {
    //now you are at bottom of #infiniteContent element
}

$(document).ready(function(){
	$.getJSON("https://jsonplaceholder.typicode.com/comments", { _page: 1, _limit:3 }, function (jsonre) {
        appendTemplate(jsonre,1);
    });
});

function appendTemplate(jsonre, pageNumber){
	//instead of this code you can use a templating plugin like "Mustache"
	for(var i =0; i<jsonre.length; i++){
  	$("#infiniteContent").append("<div class='item'><h2>"+jsonre[i].name+"</h2><p>"+jsonre[i].body+"</p></div>");
  }

  if (jsonre.length) {
    $("#infiniteContent").attr("data-page", parseInt(pageNumber)+1);
    $(window).on("scroll", initScroll);
    
    //scroll event will not trigger if window size is greater than or equal to document size
    var dh = $(document).height() , wh = $(window).height();
    if(wh>=dh){
    	initScroll();
    }
  }
  else {
    $("#infiniteContent").attr("data-page", "");
  }
}

function initScroll() {
    var t = $("#infiniteContent").offset().top;
    var h = $("#infiniteContent").height();
    var ws = $(window).scrollTop();
    var dh = $(document).height();
    var wh = $(window).height();

    if (dh - (wh + ws) < dh - (h + t)) {
        $(window).off('scroll');
        var p = $("#infiniteContent").attr("data-page");
        if (p) {
            $.getJSON("https://jsonplaceholder.typicode.com/comments", { _page: p, _limit:3 }, function (jsonre) {
                appendTemplate(jsonre, p);
            });
        }
    }
}
<script src="https://code.jquery.com/jquery-3.2.1.min.js"></script>
<div id="infiniteContent"></div>


这真的很有用。不要仅仅因为它不是最重要的答案而低估了这个答案。它工作正常,而且速度很快。
mkdavor

0

我使用侯赛因和尼克的想法编写了此函数,但我希望它对回调使用promise。我还希望无限滚动区域位于固定的div上,而不仅仅是将div发送到options对象中的窗口。我在下面的第二个链接中有一个示例。如果您想支持较旧的浏览器,建议使用Q这样的Promise库。cb方法可能是也可能不是承诺,并且无论如何都将起作用。

它的用法如下:

html

<div id="feed"></div>

js

var infScroll = infiniteScroll({
    cb: function () {
        return doSomethingPossiblyAnAJAXPromise();     
    }
});

如果您希望Feed暂时停止,则可以在cb方法中返回false。如果您已到达Feed的末尾,则非常有用。可以通过调用infiniteScroll的返回对象方法“ setShouldLoad”并传递true和示例以及上述代码来再次启动它。

infScroll.setShouldLoad(true);

无限滚动的功能是这个

function infiniteScroll (options) {
    // these options can be overwritten by the sent in options
    var defaultOptions = {
        binder: $(window), // parent scrollable element
        loadSpot: 300, //
        feedContainer: $("#feed"), // container
        cb: function () { },
    }

    options = $.extend(defaultOptions, options);
    options.shouldLoad = true;

    var returnedOptions = {
        setShouldLoad: function (bool) { options.shouldLoad = bool; if(bool) { scrollHandler(); } },
    };

    function scrollHandler () { 
        var scrollTop = options.binder.scrollTop();
        var height = options.binder[0].innerHeight || options.binder.height();
        if (options.shouldLoad && scrollTop >= (options.binder[0].scrollHeight || $(document).height()) - height - options.loadSpot) {
            options.shouldLoad = false;
            if(typeof options.cb === "function") {
                new Promise(function (resolve) {resolve();}).then(function() { return options.cb(); }).then(function (isNotFinished) {
                    if(typeof isNotFinished === "boolean") {
                        options.shouldLoad = isNotFinished;
                    }
                });
            }
        }
    }

    options.binder.scroll(scrollHandler);

    scrollHandler();

    return returnedOptions;

}

1个供稿示例,窗口为滚动条

2 feed示例,其中feed作为滚动条

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.