12

大きなデータセットを一度にロードする必要がないように、Meteorで無限スクロールを介してロードされるセクションに分割したい大量のデータセットがあります。代わりに、必要に応じてデータセットのチャンクをロードします。無限スクロールによってロードされた各セクションのライブページの更新を保持しながら、これを行うにはどうすればよいですか?

4

4 に答える 4

8

これが私が映画データベースの遊び場に使用しているコードです。jQueryイベントを試しましたが、データを継続的に転送すれば十分であると最終的に判断しました。私のテストコレクションは680レコードで、20のフィールドと1つのサムネイルフィールドがカバーごとに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はまったく応答しなくなりました。ここにローカルホストで行われたいくつかの統計(それぞれ3回実行):

limit   seconds till last record rendered.
  0     79s 
  010   121s
  020   64s  
  030   45s
  050   34s
  100   16s
  200   16s

興味深いことに、meteorサーバーがページ全体を一度に送信するのに約79秒かかりました(limit = 0)。連続ストリームが最速である必要があるため、これがどのように可能になるかはわかりません。だから、おそらく私の統計には何か面白いことがあります。何か案は?

于 2013-02-15T22:48:30.747 に答える
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を追加することを考えています

于 2013-09-04T13:56:26.803 に答える
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スクロールが(うまくいけば)機能します!

于 2013-02-17T14:24:08.100 に答える
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!

于 2013-01-05T01:33:24.083 に答える