web-dev-qa-db-ja.com

ember.jsによる無限スクロール(遅延読み込み)

ユーザーがスクロールできるアイテムの数が多いビューがあり、無限スクロールを実装してコンテンツのプログレッシブロードを有効にしたいと考えています。

一部の人々のように見えます ページネーションを行っています 誰もがすでにこれを行っており、ブログ投稿/サンプルコードを共有していますか?

54
outside2344

新しくリリースされたEmber.ListViewコンポーネントを知っていましたか?

https://github.com/emberjs/list-view

2月のサンフランシスコEmber Meetupで発表されました。以下は、使用に関するEmberコア開発者の1人であるErik Brynのスライドデッキです。

http://talks.erikbryn.com/ember-list-view/

15
commadelimited

GitHub Dashboardproject で無限スクロールメカニズムを実装しました。現在開発中です。この機能はcommit 68d1728 で追加されます。

基本的な考え方は、ビューが現在のビューポートに表示されるたびにコントローラーでLoadMoreViewメソッドを呼び出すloadMoreを用意することです。これにはjQueryプラグイン inview を使用しています。 inviewイベントに登録することができます。このイベントは、指定されたセレクターの要素が画面に表示され、消えたときに発生します。

コントローラには、ロードするアイテムがまだあるかどうか、および現在フェッチされているアイテムがあるかどうかを示すプロパティもあります。これらのプロパティは、canLoadMoreおよびisLoadingと呼ばれます。

LoadMoreViewは基本的に次のようになります。

App.LoadMoreView = Ember.View.extend({
  templateName: 'loadMore',
  didInsertElement: function() {
    var view = this;
    this.$().bind('inview', function(event, isInView, visiblePartX, visiblePartY) {
      if (isInView) Ember.tryInvoke(view.get('controller'), 'loadMore');
    });
  }
});

ここで、loadMoreテンプレートは次のように定義されます。

{{#if isLoading}}
    fetching some more stuff <img width="10" src="img/ajax-loader.gif" >
{{else}}
    {{#if canLoadMore}}
        <a {{action "loadMore" target="controller" }}>click to load more items</a>
    {{else}}
        <i>no more items</i>
    {{/if}}
{{/if}}

さらに多くのアイテムのフェッチを処理するコントローラーは、次のように実装されます。 loadMoreメソッドでは、ストアのクエリが実行され、モデルのエントリの特定のページがロードされることに注意してください。

App.EventsController = Ember.ArrayController.extend({
  currentPage: 1,

  canLoadMore: function() {
    // can we load more entries? In this example only 10 pages are possible to fetch ...
    return this.get('currentPage') < 10;
  }.property('currentPage'),

  loadMore: function() {
    if (this.get('canLoadMore')) {
      this.set('isLoading', true);
      var page = this.incrementProperty('currentPage');

      // findQuery triggers somehing like /events?page=6 and this
      // will load more models of type App.Event into the store
      this.get('store').findQuery(App.Event, { page: page });
    } else {
      this.set('isLoading', false);
    }
  }
});

残っている唯一のことは、最初にコントローラーのcontentfilter関数の結果に設定することです。したがって、新しいモデルがストアにロードされると、contentが更新されます(これは、コントローラーのfindQueryloadMoreメソッドが原因で発生します)。また、queryが呼び出されると、filterハッシュが追加されます。これにより、サーバーへの最初のクエリが作成されます。

App.eventsController = App.EventsController.create({
    content: []
});

var events = App.store.filter(App.Event, { page: 1 }, function(data) {
    // show all events; return false if a specific model - for example a specific
    // type of event - shall not be included
    return true;
});
61
pangratz

私は Emberの無限のページネーションプラグイン @pangratzの仕事に基づいて書いています。

ご質問や改善点がある場合は、問題を解決してください。

5
iHiD

Ember Infinity アドオンを使用することをお勧めします。 Ember 1.10から2.0+までをサポートしています。セットアップは比較的簡単です。テンプレート。

ルート(Productはモデル例です):

import InfinityRoute from 'ember-infinity/mixins/route';

export default Ember.Route.extend(InfinityRoute, {
  model() {
    /* Load pages of the Product Model, starting from page 1, in groups of 12. */
    return this.infinityModel('product', { perPage: 12, startingPage: 1 });
  }
});

テンプレート:

{{#each model as |product|}}
  ...
{{/each}}

{{infinity-loader infinityModel=model}}

いつ {{infinity-loader}}コンポーネントが表示されると、ルートにアクションが送信されるため、モデル配列を新しい(フェッチされた)レコードで更新することがわかります。

最初のリクエストは以下に送信されます:

/products?per_page=12&page=1

したがって、これらのクエリパラメータを処理するバックエンドAPIを準備する必要もあります。明らかにカスタマイズ可能です。 Readmeの高度な使用法セクション をご覧ください。

ListView(@commadelimitedの回答)とArrayController(@pangratzの回答)のあるビューの両方は、Ember 2.0が安定バージョンであるため、廃止/削除されました。

1
Daniel Kmak