如何使用store.filter / store.find和Ember-Data实现无限滚动?

时间:2014-01-15 01:20:45

标签: ember-data

这最初发布在discuss.emberjs.com上。看到: http://discuss.emberjs.com/t/what-is-the-proper-use-of-store-filter-store-find-for-infinite-scrolling/3798/2

但是这个网站的内容质量似乎越来越差,所以我希望StackOverflow可以拯救我。

意图:使用实现无限滚动的ember-data在ember中构建页面。

背景知识:基于emberjs.com上的ember-data api文档,特别是store.filter和store.find方法(参见:http://emberjs.com/api/data/classes/DS.Store.html#method_filter)我应该能够将路径的模型挂钩设置为商店过滤器操作的承诺。 promise的响应应该是一个过滤的记录数组,它是由过滤器函数过滤的商店中的一组项目,假设每当新项目被推入商店时不断更新。通过将此项与将项目推送到商店的store.find方法相结合,filteredRecordArray应自动更新新项目,从而更新模型并在页面上显示新项目。

例如,假设我们有一个问题路径,控制器和类型问题的模型。

App.QuestionsRoute = Ember.Route.extend({
    model: function (urlParams) {
        return this.get('store').filter('question', function (q) {
            return true;
        });
    }
});

然后我们有一个控制器,其中一些方法将调用store.find,这可能是由某些事件/操作触发的,无论是检测滚动事件还是用户显式单击以加载更多,无论此方法是否会被调用以加载更多问题。 例如:

App.QuestionsController = Ember.ArrayController.extend({
    ...
    loadMore: function (offset) {
        return this.get('store').find('question', { skip: currentOffset});
    }
    ...
});

用于呈现项目的模板:

...
{{#each question in controller}}
   {{question.title}}
{{/each}}
...

注意,使用这种方法我们 NOT 必须向store.find承诺添加一个函数,该函数显式调用this.get('model').pushObjects(questions);实际上,一旦你已经返回就试着这样做模型的过滤器记录数组不起作用。我们要么手动管理模型的内容,要么让ember-data完成工作,我非常想让Ember数据完成工作。 这是一个非常干净的API;然而,它似乎没有按照我写的方式工作。根据文档,我看不出任何错误。

使用chrome中的Ember-Inspector工具我可以看到来自第二个查找调用的新问题以“问题”类型加载到商店中,但是在我更改路由并返回之前页面不会刷新。这似乎只是观察者的一个问题,这让我觉得这将是Ember-Data中的一个错误,但我不想得出这样的结论,直到我问我是否在使用Ember-数据如预期。

如果有人不知道到底出了什么问题但是知道如何使用store.push / pushMany在jsbin中重新创建这个场景也会有所帮助。我只是不熟悉如何在商店中使用较低级别的方法。

非常感谢帮助。

1 个答案:

答案 0 :(得分:0)

我只是让这个模式适合自己,但是采用“传统”方式,即不使用store.filter()。

我管理了路由器本身的“loadMore”部分:

actions: {
    loadMore: function () {
        var model = this.controller.get('model'), route = this;
        if (!this.get('loading')) {
            this.set('loading', true);
            this.store.find('question', {offset: model.get('length')}).then(function (records) {
                model.addObjects(records);
                route.set('loading', false);
            });
        }
    }
}

既然你已经尝试过传统方式(从我在帖子中看到的讨论),似乎关键部分是使用addObjects()而不是pushObjects()。

对于记录,这是触发loadMore操作的视图的相关部分:

didInsertElement: function() {
    var controller = this.get('controller');
    $(window).on('scroll', function() {
        if ($(window).scrollTop() > $(document).height() - ($(window).height()*2)) {
            controller.send('loadMore');
        }
    });
},
willDestroyElement: function() {
    $(window).off('scroll');
}

我现在希望将loading属性移动到控制器,以便为用户提供一个很好的加载器。