我有一大堆数据,我希望将其拆分为通过Meteor中的无限滚动加载的部分,以防止必须同时加载大型数据集;相反,我会在需要时加载数据集的块。如何保留infinite scroll加载的每个部分的实时页面更新?
答案 0 :(得分:8)
这是我用于电影数据库游乐场的代码。我尝试了jQuery事件,但最终决定如果数据连续传输就足够了。我的测试集合是680条记录,有20个字段和一个缩略图字段,每个封面在10-20kb之间。这里是Coffeescript代码:
Movies = new Meteor.Collection("movies")
if Meteor.isClient
# starting with 10 items that the user sees a page fast
Session.set("queryLimit", 10)
# getting the item count from the server collection
Meteor.call 'getMoviesCount', (err, result) =>
Session.set('itemsInQuery',result)
# subscribe to a subset of the collection, and change the Session var on completion
# automatically changing the limit of the publishing function with autorun
Meteor.autorun ->
Meteor.subscribe "MoviesList", Session.get("queryLimit"), onComplete = ->
if Session.get("queryLimit") < Session.get('itemsInQuery')
queryLimit = Session.get("queryLimit") + 30 #change iterator depending on result size
Session.set("queryLimit", queryLimit )
# Client helper to add more items to handlebars template
Template.app.helpers movies: ->
Movies.find({})
if Meteor.isServer
Meteor.publish "MoviesList", (limit) ->
# show whole collections once limit is reached, by setting limit to 0
limit = 0 if limit > Movies.find().count()
console.log new Date(), limit
Movies.find({}, { limit: limit, fields: {title:1 } } ) #use fields to test different result sizes
Meteor.methods
getMoviesCount: (query) ->
return Movies.find().count()
和html:
<body>
{{> app}}
</body>
<template name="app">
{{#each movies}}
<p>{{title}}</p>
{{/each}}
</template>
我做了一些快速的性能测试,事实证明,对于每条记录的几行文本,将数据发送到客户端的最快方式是限制在100左右。我还试用了10-20kb的嵌入式缩略图在文件中。当使用更大的资产时,当限制超过30条记录时,Chrome变得非常反应迟钝。 这里有一些关于localhost的统计数据(每次运行3次):
limit seconds till last record rendered.
0 79s
010 121s
020 64s
030 45s
050 34s
100 16s
200 16s
有趣的是,当流星服务器一次性发送整个页面(限制= 0)时花了大约79秒。我不确定,这怎么可能,因为连续的流应该是最快的。所以我的统计数据可能有些有趣。有任何想法吗?
答案 1 :(得分:3)
我的解决方案与Andrej相似。 因为我在数据库中有很多记录,所以我不希望我的服务器一次性发送它们,所以在服务器上我得到了:
Meteor.publish("items", function(page) {
if(!page)
page = 1;
var limit = 30 * page;
return Items.find({}, {limit: limit};
}
客户端:
Template.templateName.items = function () {
Meteor.subscribe("items", Session.get("page"));
return Items.find({});
}
一个jQuery函数来观察页面是否到底:
$(window).scroll(function(){
if ($(window).scrollTop() == $(document).height()-$(window).height()){
Session.set("page", Session.get("page") + 1);
}
});
还要在模板创建的回调中设置页面初始页面:
Template.templateName.created = function() {
Session.setDefault("page", 1);
};
在模板中,我使用{{#each}}显示这些项目 另外,我必须检查是否没有更多记录
更好的解决方案是在创建模板时显示30,然后在滚动时再显示30个,但我不知道如何显示它们。我可能有一个解决方案,但我懒得实施,因为我不确定它是否正常工作。我正在考虑附加渲染的html
答案 2 :(得分:1)
您可以设置会话密钥,以存储您当前所在的页面。类似的东西:
Session.set("cur_page", 1);
然后将其提供给您的查询,例如:
Template.list.items = function() {
return Collection.find({}, {
skip: Session.get("cur_page") * page_size,
limit: page_size
});
}
然后,您只需使用Session.set("cur_page", 2)
更新值,您的列表将重新绘制第2页的项目.Tadaa!
答案 3 :(得分:1)
我还没试过,但它应该有效。所以,如果你有你的收藏:
var Posts = new Meteor.Collection("posts");
你的模板:
<template name="posts">
{{#each posts}}
{{> post}}
{{/each}}
</template>
这可能是你的模板助手:
Template.posts.helpers({
posts: function() {
return Posts.find({}, {limit: Session.get("current_page")*PAGE_SIZE});
}
});
其中PAGE_SIZE是每个“页面”的帖子数量。每次用户滚动到页面底部时,您需要递增“current_page”会话变量。然后模板将被更新,你的inifnite滚动(希望)有效!