如何使Backbone.js集合项独特?

Kev*_*ish 16 javascript backbone.js underscore.js

说我有这些Backbone.js模型:

var Truck = Backbone.Model.extend({});

var truck1 = new Truck();
var truck2 = new Truck();

truck1.set("brand", "Ford");
truck2.set("brand", "Toyota");
truck3.set("brand", "Honda");
truck4.set("brand", "Ford");
Run Code Online (Sandbox Code Playgroud)

然后,假设我们有一个Backbone.js集合:

var TruckList = Backbone.Collection.extend({
  model: Truck,
  comparator: function(truck) {
     return truck.get("brand");
  };

});
Run Code Online (Sandbox Code Playgroud)

我是汽车收藏家,所以有时间将每辆车添加到我的收藏中:

Trucks = new TruckList();
Trucks.add(truck1);
Trucks.add(truck2);
Trucks.add(truck3);
Trucks.add(truck4);
Run Code Online (Sandbox Code Playgroud)

只关注品牌属性,truck4是truck1的副本.我的收藏中不能有重复项.我需要我的收藏品具有独特的价值观.

我的问题是,如何从Backbone.js集合中删除重复的项目?

我应该使用Underscore.js吗?如果是这样,有人可以提供一个工作/可运行的如何执行此操作的示例.

假设如下:

1.Collection没有排序

  1. 必须对品牌属性值进行删除

  2. Ajax调用填充Truck的每个实例.这意味着在添加到集合时,您无权访问Truck属性.

Pet*_*ons 19

我会覆盖add您的TruckList集合中的方法,并使用下划线检测那里的重复项并拒绝重复.就像是.

TruckList.prototype.add = function(truck) {
    // Using isDupe routine from @Bill Eisenhauer's answer
    var isDupe = this.any(function(_truck) { 
        return _truck.get('brand') === truck.get('brand');
    });

    // Up to you either return false or throw an exception or silently ignore
    // NOTE: DEFAULT functionality of adding duplicate to collection is to IGNORE and RETURN. Returning false here is unexpected. ALSO, this doesn't support the merge: true flag.
    // Return result of prototype.add to ensure default functionality of .add is maintained. 
    return isDupe ? false : Backbone.Collection.prototype.add.call(this, truck);
}
Run Code Online (Sandbox Code Playgroud)


小智 7

实现此目的的最简单方法是确保您添加的模型具有唯一ID.默认情况下,Backbone集合不会添加具有重复ID的模型.

test('Collection should not add duplicate models', 1, function() {
    var model1 = {
        id: "1234"
    };
    var model2 = {
        id: "1234"
    };

    this.collection.add([model1, model2]);

    equal(1, this.collection.length, "collection length should be one when trying to add two duplicate models");
});
Run Code Online (Sandbox Code Playgroud)


Bil*_*uer 5

试试这个.它使用任何下划线方法来检测潜在的重复,然后转出(如果是这样).当然,你可能想要打扮一下,除了更强大之外:

TruckList.prototype.add = function(newTruck) {
  var isDupe = this.any(function(truck) { 
    return truck.get('brand') === newTruck.get('brand');
  }
  if (isDupe) return;
  Backbone.Collection.prototype.add.call(this, truck);
}
Run Code Online (Sandbox Code Playgroud)

顺便说一句,我可能会在卡车上写一个函数来进行欺骗检查,这样集合就不会对这种情况了解太多.


Nat*_* Do 5

var TruckList = Backbone.Collection.extend({
model : Truck,

// Using @Peter Lyons' answer
add : function(truck) {
    // Using isDupe routine from @Bill Eisenhauer's answer
    var isDupe = this.any(function(_truck) {
        return _truck.get('brand') === truck.get('brand');
    });
    if (isDupe) {
        // Up to you either return false or throw an exception or silently
        // ignore
        return false;
    }
    Backbone.Collection.prototype.add.call(this, truck);
},

comparator : function(truck) {
    return truck.get("brand");
} });
Run Code Online (Sandbox Code Playgroud)

VassilisB的答案很有效,但它会覆盖Backbone Collection的add()行为.因此,当您尝试执行此操作时可能会出现错误:

var truckList = new TruckList([{brand: 'Ford'}, {brand: 'Toyota'}]); 
Run Code Online (Sandbox Code Playgroud)

所以,我添加了一些检查以避免这些错误:

var TruckList = Backbone.Collection.extend({
    model : Truck,

    // Using @Peter Lyons' answer
    add : function(trucks) {
        // For array
        trucks = _.isArray(trucks) ? trucks.slice() : [trucks]; //From backbone code itself
        for (i = 0, length = trucks.length; i < length; i++) {
            var truck = ((trucks[i] instanceof this.model) ? trucks[i]  : new this.model(trucks[i] )); // Create a model if it's a JS object

            // Using isDupe routine from @Bill Eisenhauer's answer
            var isDupe = this.any(function(_truck) {
                return _truck.get('brand') === truck.get('brand');
            });
            if (isDupe) {
                // Up to you either return false or throw an exception or silently
                // ignore
                return false;
            }
            Backbone.Collection.prototype.add.call(this, truck);
       }
    },

    comparator : function(truck) {
        return truck.get("brand");
    }});
Run Code Online (Sandbox Code Playgroud)


Ted*_*ddy 2

Underscore.js 是backbone.js 的先决条件,为此提供了一个函数: http: //documentcloud.github.com/underscore/#uniq

例子:

_.uniq([1,1,1,1,1,2,3,4,5]); // returns [1,2,3,4,5]
Run Code Online (Sandbox Code Playgroud)