当用户滚动到底部时,下面的代码会加载下一页。但是,有时它会重复自己 - 当用户滚动太快时,或者在AJAX仍在加载时滚动。
有没有办法防止它多次发射?例如,在调用AJAX时无法加载任何内容,或者只能每秒调用一次AJAX?
任何帮助都会很棒。
$(window).scroll(function() {
if( $(window).scrollTop() + $(window).height() == $(document).height()) {
if (firstURL !== null) {
$.get(firstURL, function(html) { // this gets called multiple times on erratic scrolling
firstURL = '';
var q = $(html).find('.post');
l = $(html).filter('div.bottom-nav');
if( l[0].childNodes.length > 0 ){
firstURL = l[0].children[0].getAttribute('href');
} else {
firstURL = null;
}
q.imagesLoaded( function() {
jQuery(".content").append(q).masonry( 'appended', q, true );
});
});
}
}
});
答案 0 :(得分:10)
只需添加一个标志:
var ready = true; //Assign the flag here
$(window).scroll(function() {
//Check the flag here. Check it first, it's better performance wise.
if(ready && $(window).scrollTop() + $(window).height() == $(document).height()) {
ready = false; //Set the flag here
if (firstURL !== null) {
$.get(firstURL, function(html) { // this gets called multiple times on erratic scrolling
firstURL = '';
var q = $(html).find('.post');
l = $(html).filter('div.bottom-nav');
if( l[0].childNodes.length > 0 ){
firstURL = l[0].children[0].getAttribute('href');
} else {
firstURL = null;
}
q.imagesLoaded( function() {
jQuery(".content").append(q).masonry( 'appended', q, true );
});
}).always(function(){
ready = true; //Reset the flag here
});
}
}
});
答案 1 :(得分:0)
我有一个类似的问题,滚动窗口多次触发我的函数(manupulating img slider的属性)。为了有效地解决这个问题,您可以推迟执行滚动处理程序,并且使用额外的'页面滚动'标记以防止多个处理程序调用。 看看下面的例子,你肯定可以为你的案例添加方法。
$(function()
{
var pageFold = 175; //scrolling threshold
var doScroll = false; //init
var timeoutScroll = 100; //delay
var windowScrolled = false; //initial scrolling indicatior
var windowScrolling = false; //current scrolling status indicator
//load next page handler
function loadNextPage()
{
if(windowScrolling != true)
{
//and do ajax stuff - your code
}
}
//check if page scrolled below threshold handler
function foldedBelow()
{
//nice scrolled px amount detection
return (Math.max($('body').scrollTop(), $('html').scrollTop()) > pageFold);
}
//actual scrolled handler
function doWindowScroll()
{
windowScrolled = true;
if(foldedBelow())
{
loadNextPage();
}
windowScrolling = false;
}
//deffered scroll hook
$(window).scroll(function(e){
windowScrolling = true;
clearTimeout(doScroll);
doScroll = setTimeout(doWindowScroll, timeoutScroll);
});
});
答案 2 :(得分:0)
当我做这样的事情时,我实现了一个调用自定义scrolled_to_bottom
- 事件的定时滚动处理程序。
(function($, window, document){
"use strict";
var $document = $(document);
var $window = $(window);
var _throttleTimer = null;
var _throttleDelay = 100;
function ScrollHandler(event) {
//throttle event:
clearTimeout(_throttleTimer);
_throttleTimer = setTimeout(function () {
if ($window.scrollTop() + $window.height() > $document.height() - 400) {
console.log('fire_scrolled_to_bottom');
$document.trigger('scrolled_to_bottom');
}
}, _throttleDelay);
}
$document.ready(function () {
$window
.off('scroll', ScrollHandler)
.on('scroll', ScrollHandler);
});
}(jQuery, window, document));
然后在我的对象处理重新加载时,我用标志检查绑定了该事件,如果它已经加载了。
handler = {
...,
isLoading: false,
bind: {
var self = this;
$document.on('scrolled_to_bottom', function () {
if (self.isLoading) {
return;
}
self.nextPage();
});
}
nextPage(): function () {
var self = this;
this.isLoading = true;
$.ajax({
url: url,
data: self.searchData,
dataType: "json",
type: "POST",
success: function (json) {
// do what you want with respone
},
error: function (xhr, statusText, errorThrown) {
bootbox.alert('An error occured.');
},
complete: function () {
self.isLoading = false;
}
});
},
init: function () {
this.doInitStuff();
this.bind();
}
}
通过这种方式,我分离了关注点并可以很好地重用触发器,并且如果在重新加载时发生其他事情,则可以轻松添加功能。
答案 3 :(得分:0)
尝试存储某种数据,用于存储页面当前是否正在加载新项目。也许是这样的:
$(window).data('ajaxready', true).scroll(function(e) {
if ($(window).data('ajaxready') == false) return;
if ($(window).scrollTop() >= ($(document).height() - $(window).height())) {
$('div#loadmoreajaxloader').show();
$(window).data('ajaxready', false);
$.ajax({
cache: false,
url: 'loadmore.php?lastid=' + $('.postitem:last').attr('id'),
success: function(html) {
if (html) {
$('#postswrapper').append(html);
$('div#loadmoreajaxloader').hide();
} else {
$('div#loadmoreajaxloader').html();
}
$(window).data('ajaxready', true);
}
});
}
});
在发送Ajax请求之前,会清除一个标志,表示该文档尚未准备好接收更多Ajax请求。一旦Ajax成功完成,它就会将标志设置为true,并且可以触发更多请求。
复制:jQuery Infinite Scroll - event fires multiple times when scrolling is fast
答案 4 :(得分:0)
这是我的解决方案。您可以获得一个想法并将其应用到您的想法。也是为了帮助别人。
以下是示例代码。
//declare outside
var loadInterval = null;
// .....
// .....
$(window).scroll(function() {
if ($('.loadmore').isOnScreen() === true) {
//No waiting registered, we can run loadMore
if(loadInterval === null) {
// This console.log executes in 5 seconds interval
console.log('Just called ' + new Date());
// your code in here is prevented from running many times on scroll
// Register setTimeout() to wait for some seconds.
// The code above will not run until this is nullified
loadInterval = setTimeout(function(){
//Nullified interval after 5 seconds
loadInterval = null;}
, 5000);
}
}
});
我在这里发布了jQuery的IsOnScreen()插件(我发现它在stackoverflow上:)
$.fn.isOnScreen = function() {
var win = $(window);
var viewport = {
top: win.scrollTop(),
left: win.scrollLeft()
};
viewport.right = viewport.left + win.width();
viewport.bottom = viewport.top + win.height();
var bounds = this.offset();
bounds.right = bounds.left + this.outerWidth();
bounds.bottom = bounds.top + this.outerHeight();
return (!(viewport.right < bounds.left || viewport.left > bounds.right || viewport.bottom < bounds.top || viewport.top > bounds.bottom));
};