正确地对backbone.js集合进行快速排序

kik*_*iyo 42 backbone.js

我可以成功地做到这一点:

App.SomeCollection = Backbone.Collection.extend({
  comparator: function( collection ){
    return( collection.get( 'lastName' ) );
  }
});
Run Code Online (Sandbox Code Playgroud)

如果我想要一个仅按'lastName'排序的集合,那就太好了.但我需要动态完成这种排序.有时,我需要改为排序,比如'firstName'.

我的彻底失败包括:

我尝试将指定变量的额外变量传递给sort()on.那没用.我也尝试过sortBy(),但也没用.我尝试将自己的函数传递给sort(),但这也不起作用.将用户定义的函数传递给sortBy()结果没有each方法,从而破坏了新排序的主干集合.

有人能提供一个实际的例子,通过一个未硬编码到比较器函数中的变量进行排序吗?或者你有任何黑客有效吗?如果没有,工作sortBy()电话?

Jos*_*arl 37

有趣的问题.我会在这里尝试一下策略模式的变体.您可以创建排序函数的哈希,然后comparator根据所选的哈希成员进行设置:

App.SomeCollection = Backbone.Collection.extend({
    comparator: strategies[selectedStrategy],
    strategies: {
        firstName: function () { /* first name sorting implementation here */ }, 
        lastName: function () { /* last name sorting implementation here */ },
    },
    selectedStrategy: "firstName"
});
Run Code Online (Sandbox Code Playgroud)

然后,您可以通过更新selectedStrategy属性的值来动态更改排序策略.

编辑:我睡觉后意识到这不会像我上面写的那样工作,因为我们正在传递一个对象文字Collection.extend.该comparator属性将被评估一次,在创建对象的时候,所以,除非被迫这样做,所以它不会在飞行中改变.可能有一种更简洁的方法可以做到这一点,但这证明了即时切换比较器功能:

var SomeCollection = Backbone.Collection.extend({
    comparator: function (property) {
        return selectedStrategy.apply(myModel.get(property));
    },
    strategies: {
        firstName: function (person) { return person.get("firstName"); }, 
        lastName: function (person) { return person.get("lastName"); },
    },
    changeSort: function (sortProperty) {
        this.comparator = this.strategies[sortProperty];
    },
    initialize: function () {
        this.changeSort("lastName");
        console.log(this.comparator);
        this.changeSort("firstName");
        console.log(this.comparator);        
    }                                                                                        
});

var myCollection = new SomeCollection;
Run Code Online (Sandbox Code Playgroud)

这是一个证明这一点的jsFiddle.

我认为,所有问题的根源在于,在创建对象时会立即评估JavaScript对象文字的属性,因此如果要更改属性,则必须覆盖该属性.如果你尝试将某种切换写入属性本身,它将被设置为初始值并保持在那里.

这是一篇很好的博客文章,在稍微不同的背景下讨论这个问题.


小智 17

通过为其分配新功能并调用sort来更改为比较器功能.

// Following example above do in the view:

// Assign new comparator
this.collection.comparator = function( model ) {
  return model.get( 'lastname' );
}

// Resort collection
this.collection.sort();

// Sort differently
this.collection.comparator = function( model ) {
  return model.get( 'age' );
}
this.collection.sort();
Run Code Online (Sandbox Code Playgroud)


kik*_*iyo 13

所以,这是我真正有效的解决方案.

  App.Collection = Backbone.Collection.extend({

    model:App.Model,

    initialize: function(){
      this.sortVar = 'firstName';
    },

    comparator: function( collection ){
      var that = this;
      return( collection.get( that.sortVar ) );
    }

  });
Run Code Online (Sandbox Code Playgroud)

然后在视图中,我必须像MICKEY MOUSE一样:

this.collections.sortVar = 'lastVar'

this.collections.sort( this.comparator ).each( function(){
  // All the stuff I want to do with the sorted collection... 
});
Run Code Online (Sandbox Code Playgroud)

由于Josh Earl是唯一一个尝试解决方案的人,他确实引导我朝着正确的方向前进,我接受了他的回答.谢谢Josh :)