如何覆盖Backbone Collection remove方法然后调用parent

时间:2014-02-22 12:07:43

标签: javascript backbone.js

我正在关注SO和其他地方的帖子中的建议,但无法使其发挥作用。

我想覆盖所有Backbone Collections上的remove函数,以便在删除所有模型后触发'removed'事件。

我试过这个:fiddle here

Backbone.Collection.prototype.remove = function(models, options){
    console.log('removing');
    Backbone.Collection.prototype.remove.call(this, models, options);
    this.trigger('removed', models);    
};

var MyColl = Backbone.Collection.extend({ });
var MyModel = Backbone.Model.extend({ });

var myColl = new MyColl();
var myModel = new MyModel();

myColl.add(myModel);
myColl.remove(myModel);

...但它似乎递归地调用自身,并且从不触发父(基础)删除方法。

如何正确覆盖remove方法并调用基本方法?

4 个答案:

答案 0 :(得分:3)

你覆盖remove然后在Backbones Collection原型上调用remove,所以它会调用它自己。

相反,您应该在实现中覆盖它:

var MyCollection = Backbone.Collection.extend({
  remove: function(models, options) {
    // Do your stuff
    // ..

    // Call the parent
    Backbone.Collection.prototype.remove.call(this, models, options)
  }
});

然后,您当然可以扩展MyCollection而不是Backbone.Collection来继承其他控制器中的此功能。

updated version of your fiddle

答案 1 :(得分:2)

我最喜欢的方法是使用Underscore的wrap(),特别是因为Underscore在Backbone中默认可用。我个人喜欢使用wrap()因为它用简单的英语清楚地表明发生了什么,如下:

Backbone.Collection.prototype.remove = _.wrap(
    Backbone.Collection.prototype.remove,
    function(original_remove, models, options) {
        // Capture original function arguments
        var original_args = Array.prototype.splice.call(arguments, 0, 1);

        // Before
        console.log('removing');

        // Call original function with original arguments
        original_remove.apply(this, original_args);

        // After
        this.trigger('removed', models);
    });

唯一需要注意的是Array.prototype.splice调用,它会剥离第一个参数(Underscore设置为原始函数)。但是,这允许我们将apply()与原始参数一起使用,这比call()更灵活,因为它处理任意数量的参数而不必明确命名它们。

请注意使用Array.prototype.splice而不是arguments.splice(),这是必需的arguments不是完整的Javascript数组类型,并且不会在其自己的原型中携带splice方法。

答案 2 :(得分:0)

你覆盖原型,所以当你调用它时,它会继续递归。 您需要创建一个可以扩展的新基础集合,或者将功能推送到现有扩展中 - 具体取决于您希望如何重复使用它。

var MyBaseCollection = Backbone.Collection.extend({
    remove: function(models, options){
        console.log('removing');
        Backbone.Collection.prototype.remove.call(this, models, options);
        this.trigger('removed', models);    
    }
});

var MyColl = MyBaseCollection.extend({ });

或直接将其添加到MyColl中。

答案 3 :(得分:0)

你这样做:

var remove = Backbone.Collection.prototype.remove;
Backbone.Collection.prototype.remove = function(models, options){
    console.log('removing');
    remove.call(this, models, options);
    this.trigger('removed', models);    
};

Here is an example