从视图重新排序主干集合

时间:2013-05-04 15:00:47

标签: javascript backbone.js backbone-views

我在点击活动中使用我的收藏时遇到问题。为每个模型触发并执行排序功能,但是不会触发重置事件,也不会在视图上更改集合。

我在我的收藏中定义了多个排序标准,如:

feNoRequire.Collections.CompetitionCollection = Backbone.Collection.extend({

    model: feNoRequire.Models.CompetitionModel,
    comparator: function (property) {
        return selectedStrategy.apply(model.get(property));
    },
    strategies: {
        name: function (competition) { return competition.get("name"); }, 
        nameReverse: function (competition) { console.log(competition); return -competition.get("name"); }, 
        date: function (competition) { console.log(competition.get("event")); },
    },
    changeSort: function (sortProperty) {
        this.comparator = this.strategies[sortProperty];
    },
    initialize: function () {
        this.changeSort("name");   
    }

});

在我的观看档案中:

initialize: function(options){
        this.evnt = options.evnt;

        this.collection.on('reset', this.render, this);     
        this.evnt.bind("orderByDate", this.changeSort, this);
    },

    changeSort: function(){
        this.collection.changeSort('nameReverse')
        this.collection.sort();
    },

    render: function() {
        console.log("going for rendering")
        var renderedContent = this.template({competitions: this.collection.toJSON()});

        $(this.el).html(renderedContent);
        return this;
    }

关于如何解决这个问题的任何想法?

修改 在下面的答案之后,渲染现在被触发,但是对象只在初始化时被排序。任何后续排序都按初始顺序返回集合 - this.changeSort(“name”);

我的模特:

feNoRequire.Models.CompetitionModel = Backbone.Model.extend({
    initialize: function(){
        this.attributes.events = new feNoRequire.Collections.EventCollection(this.attributes.events);
    }
});

3 个答案:

答案 0 :(得分:6)

来自fine manual

  

排序 collection.sort([options])

     

[...]调用sort会在集合上触发"sort"事件。

因此调用sort不会触发"reset"事件(因为集合未获得reset),它会触发"sort"事件。所以你想:

this.collection.on('sort', this.render, this);

以及绑定到"reset"

演示:http://jsfiddle.net/ambiguous/34Ena/


我看到你正在调用changeSort('nameReverse')并且排序会这样做:

nameReverse: function (competition) {
    return -competition.get("name");
}

这不符合你的想法,否定一个非数字字符串会给你NaN。这意味着您最终会尝试对NaN列表进行排序,所有这些都是false

NaN  < NaN
NaN  > NaN
NaN == NaN

所以排序NaN列表并没有用。如果要反向排序字符串,则必须使用双参数比较器函数:

nameReverse: function(a, b) {
    a = a.get('name');
    b = b.get('name');
    return a < b ?  1
         : a > b ? -1
         :          0;
}

答案 1 :(得分:1)

您可以收听集合的sort事件并执行渲染。尝试将事件绑定更改为:

this.collection.on('sort reset', this.render, this);     

答案 2 :(得分:1)

非常好的代码设置。我非常喜欢你通过策略对象调用排序函数的方式。

我认为此代码的问题源于以下部分:

comparator: function (property) {
    return selectedStrategy.apply(model.get(property));
},

根据文档,比较器函数采用模型或迭代器(不是属性),也不确定selectedStrategy应该引用什么...这是另一个函数,它存在于你提供的代码之外的某个地方?

Apply还会将一个上下文对象作为“this”和一组参数。根据适用的MDN文档:

fun.apply(thisArg[, argsArray])

除非您的模型的属性是您想要用作“this”的对象,否则我认为这不正常。也许如果我能看到模型定义会更有意义。

编辑:在阅读其他回复后,我意识到你正在观看重置事件而不是排序,所以我的回答可能只是对你的代码的误解,而不是问题毕竟:)