[英]Backbone.js: how to unbind from events, on model remove
在骨干網中,我們有一個使用事件聚合器的應用程序,位於window.App.Events
現在,在許多視圖中,我們綁定到該聚合器,我手動在視圖上編寫了一個destroy函數,該函數處理來自該事件聚合器的解除綁定然后刪除視圖。 (而不是直接刪除視圖)。
現在,某些模型我們也需要這個功能,但我無法弄清楚如何解決它。
某些模型需要綁定到某些事件,但也許我錯了,但如果我們從集合中刪除一個模型,由於這些綁定到仍然存在的事件聚合器,它會保留在內存中。
模型上沒有真正的刪除功能,就像視圖一樣。 那我怎么解決這個問題呢?
編輯請求,一些代碼示例。
App = {
Events: _.extend({}, Backbone.Events)
};
var User = Backbone.Model.extend({
initialize: function(){
_.bindAll(this, 'hide');
App.Events.bind('burglar-enters-the-building', this.hide);
},
hide: function(burglarName){
this.set({'isHidden': true});
console.warn("%s is hiding... because %s entered the house", this.get('name'), burglarName);
}
});
var Users = Backbone.Collection.extend({
model: User
});
var House = Backbone.Model.extend({
initialize: function(){
this.set({'inhabitants': new Users()});
},
evacuate: function(){
this.get('inhabitants').reset();
}
});
$(function(){
var myHouse = new House({});
myHouse.get('inhabitants').reset([{id: 1, name: 'John'}, {id: 1, name: 'Jane'}]);
console.log('currently living in the house: ', myHouse.get('inhabitants').toJSON());
App.Events.trigger('burglar-enters-the-building', 'burglar1');
myHouse.evacuate();
console.log('currently living in the house: ', myHouse.get('inhabitants').toJSON());
App.Events.trigger('burglar-enters-the-building', 'burglar2');
});
在jsFiddle上查看此代碼(控制台中的輸出): http : //jsfiddle.net/saelfaer/szvFY/1/
正如您所看到的,我不會綁定模型上的事件,而是綁定到事件聚合器。 來自模型本身的解除綁定事件是沒有必要的,因為如果它被移除,沒有人會再次觸發它上面的事件。 但eventAggregator始終處於適當位置,以便於在整個應用程序中傳遞事件。
代碼示例顯示,即使從集合中刪除它們,它們也不再存在於房屋中,但是當竊賊進入房屋時仍然執行hide命令。
我看到即使綁定事件方向是這樣的方式Object1 - > listen - > Object2它必須被刪除,以便Object1丟失任何活動引用。
並且看到聽模型remove
事件不是解決方案,因為它沒有在Collection.reset()
調用中調用,那么我們有兩個解決方案:
正如@dira sais在這里,您可以覆蓋Collection._removeReference
以更正確地清除方法。
我不喜歡這個解決方案有兩個原因:
super
的方法。 Collection.reset()
調用 相反的是:不添加更深層的功能 ,而是添加更高的功能 。
然后,不是直接調用Collection.reset()
,而是可以在靜默刪除之前調用cleanUp模型的實現:
cleanUp: function( data ){
this.each( function( model ) { model.unlink(); } );
this.reset( data );
}
代碼的分類器版本可能如下所示:
AppEvents = {};
_.extend(AppEvents, Backbone.Events)
var User = Backbone.Model.extend({
initialize: function(){
AppEvents.on('my_event', this.listen, this);
},
listen: function(){
console.log("%s still listening...", this.get('name'));
},
unlink: function(){
AppEvents.off( null, null, this );
}
});
var Users = Backbone.Collection.extend({
model: User,
cleanUp: function( data ){
this.each( function( model ) { model.unlink(); } );
this.reset( data );
}
});
// testing
var users = new Users([{name: 'John'}]);
console.log('users.size: ', users.size()); // 1
AppEvents.trigger('my_event'); // John still listening...
users.cleanUp();
console.log('users.size: ', users.size()); // 0
AppEvents.trigger('my_event'); // (nothing)
檢查jsFiddle 。
我們首先驗證Object1在Object2中監聽事件是否會在Obect2 - > Object1的方向上創建一個鏈接:
在上面的圖像中,我們看到模型(@ 314019)不僅被users
集合保留,而且還被觀察到的AppEvents
對象保留。 看起來像程序員透視鏈接的事件是偵聽的對象 - >到 - >被偵聽的對象但實際上完全相反: 被偵聽的對象 - >到 - >正在偵聽的對象 。
現在,如果我們使用Collection.reset()
清空Collection,我們看到已刪除users
鏈接,但AppEvents
鏈接仍然存在:
users
鏈接已經消失,鏈接OurModel.collection
我認為是Collection._removeReference()
作業的一部分。
當我們使用我們的Collection.cleanUp()
方法時,對象從內存中消失,我無法讓Chrome.profile
工具明確告訴我@ 314019對象已被刪除,但我可以看到它已不再是內存對象 。
我認為干凈的引用過程是Backbone
一個棘手的部分。
從Collection
刪除Model
,集合會注意unbind
模型上與其自身綁定的集合的任何事件。 檢查這個私有的Collection方法 。
也許你可以在你的聚合器中使用這樣的技術:
// ... Aggregator code
the_model.on( "remove", this.unlinkModel, this );
// ... more Aggregator code
unlinkModel: function( model ){
model.off( null, null, this );
}
在這種情況下,綁定的方向是Aggregator - > Model 。 如果方向相反我不認為你必須在模型刪除后進行任何清潔。
我沒有像fguillen建議的那樣用cleanUp
包裝Collection
的reset
,而是直接擴展Collection
和覆蓋reset
。 原因是cleanUp
僅在客戶端代碼中生效,但在庫(即Backbone )中則不生效。 例如, Collection.fetch
可以在內部調用Collection.reset
。 除非修改Backbone的源代碼,否則在調用Collection.fetch
之后,我們無法從事件中取消綁定模型(如cleanUp
)。
基本上,我建議的代碼段如下:
var MyCollection = Backbone.Collection.extend({
reset: function(models, options) {
this.each(function(model) {
model.unlink(); // same as fguillen's code
});
Backbone.Collection.prototype.reset.apply(this, arguments);
}
});
稍后,我們可以基於MyCollection
創建新的集合。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.