如何在Backbone中从未排序的数据中呈现已排序的集合?

时间:2014-09-07 11:27:01

标签: sorting backbone.js

我从服务器获取未分类的数据,并希望使用Backbone在排序列表中显示它。为此,我在集合中使用comparator。但是,当一次向集合添加多个模型时,Backbone会以不方便的顺序触发add个事件。

以下是一个说明我的问题的示例(JSFiddle:http://jsfiddle.net/5wtnjj8j/2/):

initialize的{​​{1}}函数中,我将三个人添加到集合中(请注意,它们未正确排序)。每次Backbone将其中一个模型插入集合时,它会触发PersonCollectionView事件并调用我的add函数。此函数输出插入人员的名称和插入人员的索引。

这是我得到的输出:

personAdded

显然,索引是正确的(即按名称排序)。 但是为什么Backbone按照指定模型的顺序触发 insert "Alice" at index: 0 insert "Eve" at index: 2 insert "Bob" at index: 1 事件,而不是按索引的顺序?

我认为这种行为是违反直觉的,因为它很难构建排序的视图列表。例如,假设我想为模型构建add。插入Alice会起作用(因为她的索引是0),但是当第二个<ul>事件到来时,我即将在索引2处插入Eve而没有首先在索引1接收Bob。

是否有一个特殊原因导致Backbone以“错误”顺序触发 add 事件,是否有办法接收按索引排序的事件?


模型

add

集合

var Person = Backbone.Model.extend({
    defaults: {
        name: 'Unknown'
    }
});

查看

var PersonCollection = Backbone.Collection.extend({
    model: Person,
    comparator: 'name'
});

2 个答案:

答案 0 :(得分:1)

解决问题的一个简单方法是在将模型列表添加到集合之前对其进行排序。

var models = [{name: 'Alice'}, {name: 'Eve'}, {name: 'Bob'}];
this.collection.add(_.sortBy(models, 'name'));

以下是http://jsfiddle.net

的示例

Backbone按照您提供的顺序添加模型并在此之后对其进行排序,并在第一个事件到达personAdded功能之前Backbone已经添加了所有模型,这就是为什么Eve的索引2而不是1


对于fetch来电,请尝试重新定义parse功能:

var PersonCollectionView = Backbone.View.extend({
  ...
  parse: function(response) {
    return _.sortBy(response, 'name')
  }

答案 1 :(得分:0)

我相信您也可以使用未排序的数组

创建一个新集合并实例化该集合
initialize: function() {

        var models = [{name: 'Alice'}, {name: 'Eve'}, {name: 'Bob'}];
        this.collection = new PersonCollection(models );

        this.collection.on('add', this.personAdded, this);
    },

您可以采取的另一种方法是在添加项目后声明您的集合添加绑定。

   initialize: function() {
        this.collection = new PersonCollection();

        var models = [{name: 'Alice'}, {name: 'Eve'}, {name: 'Bob'}];
        this.collection.add(models);

        this.collection.on('add', this.personAdded, this);
    },

编辑:创建集合视图的替代方法。视图通常不是一个好主意,知道容器在哪里/什么(在这种情况下为正文)。从render()函数返回视图内容是一种更好的做法。然后将视图的el添加到正文中。

var PersonCollectionView = Backbone.View.extend({
    initialize: function(opts) {        
        var models = [{name: 'Alice', index:1}, {name: 'Eve', index:2}, {name: 'Bob', index:3}];

        this.collection = new PersonCollection(models);
        this.collection.on('add', this.personAdded, this);
    },
    personAdded: function(model, collection, options) {
        var index = collection.indexOf(model);
        var message = 'insert "' + model.get('name') + '" at index: ' + model.get('index') + '<br>';

        this.$el.append(message);
    },
    render: function(){
        this.collection.each(function(model){
            this.$el.append('insert "' + model.get('name') + '" at index: ' + model.get('index')+"</br>");
        },this);
        return this;    //making it chainable (render().$el);
    }
});

//from server
var personCollectionView = new PersonCollectionView();

$('body').append(personCollectionView.render().el);