55

我有一个视图,其中可以有大量项目供用户滚动浏览,我想实现无限滚动以启用内容的渐进式加载。

看起来有些人已经完成了分页,但谷歌并没有提出任何人讨论他们如何使用 Ember/Ember Data 完成无限列表。任何人都已经解决了这个问题并有一篇博客文章/示例代码可以分享?

4

4 回答 4

61

GitHub Dashboard 我已经在项目中实现了无限滚动机制,我目前正在开发中。该功能在提交68d1728中添加。

基本思想是每次视图在当前视口上可见时LoadMoreView调用控制器上的方法。loadMore我为此使用了 jQuery 插件inview。它允许您注册一个inview事件,当指定选择器的元素在屏幕上可见以及它消失时触发该事件。

控制器还具有指示是否有更多项目要加载以及当前是否已获取项目的属性。这些属性称为canLoadMoreisLoading

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);
    }
  }
});

剩下的唯一事情是最初将content控制器的 设置为filter函数的结果,因此content当新模型加载到存储中时会更新(这是由于控制器findQuery中的方法而发生loadMore的)。此外,在调用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;
});
于 2012-08-12T21:11:23.763 回答
15

你知道新发布的 Ember.ListView 组件吗?

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

它是在二月份的旧金山 Ember 聚会上宣布的。下面是来自 Ember Core 开发人员之一的 Erik Bryn 关于使用它的幻灯片:

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

于 2013-03-13T19:26:01.690 回答
5

我正在根据@pangratz 的工作为 Ember 编写一个无限分页插件。

如果您有任何问题或需要改进,请在那里提出任何问题。

于 2013-04-02T23:13:30.613 回答
1

我建议使用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 的 Advanced Usage 部分

注意

自 Ember 2.0 稳定版起,使用 (@commadelimited's answer) 和使用ListView(@pangratz's answer) 的视图ArrayController均已弃用/删除。

于 2015-09-27T16:52:52.770 回答