我正在关注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方法并调用基本方法?
答案 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
来继承其他控制器中的此功能。
答案 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);
};