jQuery 无限滚动 "重置"

14
我正在为一个网站使用无限滚动的 jQuery 插件 (https://github.com/paulirish/infinite-scroll)。

一切都很好,除了我的页面是一个搜索页面,所以...问题出现在这里:

1)进入页面后,浏览器会自动定位并返回您周围的项目列表 (例如酒吧)...对于此列表,需要使用无限滚动来避免分页。一切都运行正常直到这里...但是我可能会达到“无限页面末尾”,然后插件就会从滚动中“解绑”。

2)现在...当您想要手动在输入文本中插入地址时,您可以自由地这样做...您编写地址,按下回车键...然后通过 ajax (无页面刷新) 查找纬度/经度,定位地址,更改无限滚动的导航链接...然后,我感到很蠢,但我想不出一种方法来“重新激活”或“重新绑定”插件到事件上...因此,我的“新搜索结果”没有新的“无限滚动”实例...

(页面正确“拆分”并正确返回 JSON 尝试更改“page=NUMBER”)

这是控制台中发生的情况:

["math:", 0, 468]
jquery.infinitescroll.min.js:20["heading into ajax", 
Array[2]
    0 : "/ajax/getCoworkings/?page="
    1 : "&latitude=52.5234051&longitude=13.4113999&distance=12"
    length : 2
    __proto__ : Array[0]
]
jquery.infinitescroll.min.js:20["Using JSON via $.ajax() method"]
jquery.infinitescroll.min.js:20["Error", "end"]
jquery.infinitescroll.min.js:20["Binding", "unbind"]

在执行“unbind”之后,我无法再次绑定它,因此在下一次搜索结果中拥有无限滚动……

8个回答

28

通过$.data,infinitescroll将其所有实例数据存储在元素本身上,因此删除这些实例数据是完全重置infinitescroll的唯一可靠方法。

这两行代码应该可以彻底销毁infinitescroll并清除其痕迹。

$elem.infinitescroll('destroy');
$elem.data('infinitescroll', null);

// 现在可以正常重新初始化无限滚动,而不会有来自先前实例的冲突或残留问题。

注意,截至2012年6月,之前的所有答案在最新版本的jquery.infinitescroll(v2.0)中都无法为我工作。


5
我也在使用v2版本,这是唯一对我有效的解决方案。 - Nathan Hurst
3
如果有其他人在2019年阅读这篇文章,我只能通过使用$elem.infiniteScroll('destroy');$elem.data('infiniteScroll', null);来使v3.0.5版本正常工作。注意大小写敏感。 - Florian

5
解决了。
我已经添加了:
if (xhr == 'destroy') {
    $.removeData(this.element[0]);
}

在函数中
_error: function infscr_error(xhr) {

在第228行。

也许这不是最好的方法,但这正是我所需要的。

现在我所做的基本上就是你所建议的:

1.

$("#myelement").infinitescroll("destroy");

2.

$("#myelement").infinitescroll(WHATEVER_SETTINGS);

无需修改“pathParse”值即可实现功能,
但这是因为我正在使用jQuery修改选择器(next/nav)。


我还必须注释掉这一行代码//$(opts.navSelector).hide();,才能让它正确地工作。因为我们隐藏了这个元素,所以它会给opts.pixelsFromNavToBottom提供错误的结果。如果你只创建了一次插件,这之前并不重要,但在我们的情况下,它被创建了多次,并且导致了pixelsFromNavToBottom值的错误。 - Yehia A.Salam
注意:截至2012年6月,此解决方案似乎已不再有效。 - fisch0920

3

这里没有提到,但是(至少在我的版本中)您还需要设置两个变量才能重新实例化Infinite Scroll。您还需要重新绑定它。以下是代码:

$('#cardContainer').infinitescroll('destroy'); // Destroy

// Undestroy
$('#myContainer').infinitescroll({                      
    state: {                                              
        isDestroyed: false,
        isDone: false                           
}
});

InitInfiniteScroll(); // This is a wrapper for the standard initialization you need

// Re-initialize
$('#myContainer').infinitescroll('bind');

3

2

因为我的代码会根据用户的操作更新目标URL,而不仅仅是依靠计数器,所以我不得不做类似的事情。

最终,我实现了以下reset方法,然后可以使用$container('reset')调用它:

reset: function infrscr_reset() {
        this.options.state.isDone = false;
        this.options.state.isDuringAjax = false; // I needed this, others may not
        this._resetmsg();
        this._binding('bind');
    },

我还实现了一个私有方法来重置悬停消息,否则它将继续给出“没有更多页面”的通知。

_resetmsg: function infscr_resetmsg() {
        var opts = this.options;
        opts.loading.msg = $('<div id="infscr-loading"><img alt="Loading..." src="' + opts.loading.img + '" /><div>' + opts.loading.msgText + '</div></div>');
        this._debug('Reset loading message');
    },

1

第三项)

if (xhr == 'destroy') {
    $.removeData(this.element[0]);

}

最新版本似乎不太好用。砖石结构抱怨说“无法在初始化之前调用砖石结构的方法;尝试调用方法'reload'”。

$container.css('display','none');
$container.html(htmlOutput).imagesLoaded( function(){
             $container.css('display','block');
             $container.masonry('reload');
});

// I have to do this in order to "reset" the stage
$container.infinitescroll('destroy'); // Destroy

// Undestroy
$container.infinitescroll({                      
   state: {
      isDestroyed: false,
      isDone: false
   }
});

// Init.
$container.infinitescroll({
   navSelector  : '#page-nav',    // selector for the paged navigation 
   nextSelector : '#page-nav a',  // selector for the NEXT link (to page 2)
   itemSelector : '.tile',     // selector for all items you'll retrieve
   loading: {
     finishedMsg: '',
     msgText: '',
     img: url + 'img/ajax-loader.gif'
   }
},
// trigger Masonry as a callback
function( newElements ) {
    // hide new items while they are loading
    var $newElems = $( newElements ).css({ opacity: 0 });
    // ensure that images load before adding to masonry layout
    $newElems.imagesLoaded(function(){
        // show elems now they're ready
        $newElems.animate({ opacity: 1 });
        $container.append($newElems).masonry('appended', $newElems, true); 
    });
 }
);

// Re-initialize
$container.infinitescroll('bind');

1

假设您已经创建了无限滚动功能:

//This will initiate with default values for example purpose
$("#myelement").infinitescroll();

那么你不能简单地完全销毁该实例吗:

$("#myelement").infinitescroll("destroy");
//Reset anything else that may cause the page to blow up here
//And then create a new instance with different path variables:
//Note, obviously you'll be initializing it with custom selectors/settings etc so include those as well
$("#myelement").infinitescroll({pathParse:["/ajax/getCoworkings/?page=","&latitude=52.5234051&longitude=13.4113999&distance=12"]});

如果您不定义pathParse,脚本会尝试自行解决。如果您定义了它,它将使用您提供的内容。这并不是非常优雅,更像是一种hack,但目前在无限滚动中严格来说并不支持更改pathParse。


那没什么用,我仍然遇到同样的问题,无论是在“destroy”之后还是没有新的“.infinitescroll()” :-| - ricricucit
啊,使用removeData()函数的想法很好。我认为它需要被引入到插件的销毁函数中。这很困难,因为实际上你正在尝试从实例本身内部销毁该实例! - Beaver6813
这个评论是和我的回答相关的,只是放错了位置吗? :P - ricricucit

0

您可以通过将以下代码添加到您的无限滚动声明中来实现此操作。

errorCallback : function() {
    isc.getContainer().infinitescroll('destroy');
    $.removeData(this);
},

注意:这个代码不在infinitescroll.js文件中,它应该在你的自定义无限滚动声明中。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接