Backbone.js:如何解除事件的绑定,在模型删除 [英] Backbone.js: how to unbind from events, on model remove

查看:125
本文介绍了Backbone.js:如何解除事件的绑定,在模型删除的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在骨干网中,我们有一个应用程序,使用一个事件聚合器,位于 window.App.Events
上,在许多视图中,我们绑定到聚合器,我手动在一个视图上写了一个destroy函数,它处理从该事件聚合器取消绑定,然后删除该视图。 (而不是直接删除视图)。



现在,有一些模型,我们需要这个功能,但我不知道如何解决它。某些型号需要绑定某些事件,但也许我误以为是,因为我们从一个集合中删除一个模型,因为这些绑定到事件,它会保留在内存中聚合器仍然在位。



模型上没有真正的删除功能,就像视图一样。
所以我如何处理这个?



编辑
请求,一些代码示例。 b
$ b

  App = {
事件:_.extend({},Backbone.Events)
};

var User = Backbone.Model.extend({

initialize:function(){
_.bindAll(this,'hide');
App.Events.bind('防盗 - 进入建设',this.hide);
},

hide:function(burglarName){
this.set ({'isHidden':true});
console.warn(%s正在隐藏...因为%s进入房子,this.get('name'),burglarName);
}

});

var Users = Backbone.Collection.extend({

model:User

});

var House = Backbone.Model.extend({

initialize:function(){
this.set({'inhabitants':new Users()} );
},

撤离:function(){
this.get('inhabitants')。reset();
}

});



$(function(){

var myHouse = new House({});

myHouse。 get('inhabitants')。reset([{id:1,name:'John'},{id:1,name:'Jane'}]);

console.log住在家里:',myHouse.get('居民')toJSON());

App.Events.trigger('burglar-enter-the-building','burglar1');

myHouse.evacuate();

console.log('当前住在房子里',myHouse.get('居民')toJSON());

App.Events.trigger('burglar-enter-the-building','burglar2');

});

在jsFiddle(控制台输出)中查看此代码: http://jsfiddle.net/saelfaer/szvFY/1/



如你所见,我不绑定到事件在模型上,而是一个事件聚合器。
从模型本身解除绑定的事件是没有必要的,因为如果它被删除,没有人会再次触发一个事件。但是eventAggregator始终存在,以便通过整个应用程序传递事件。



代码示例显示,即使他们从集合中删除,不要住在家里,但是当窃贼进入房子时,仍然执行隐藏命令。

解决方案

我看到即使绑定事件方向是这样的方式 Object1 - > listen - > Object2 ,它必须被删除,以便 Object1 丢失任何存在的引用。



看到,由于在集合中没有调用,所以听到模型删除事件不是一个解决方案。 reset() call,那么我们有两个解决方案:



1。覆盖正常Collection CleanUp



As @ dira sais here ,您可以覆盖 Collection._removeReference 以更好地清理该方法。



我不喜欢这个解决方案有两个原因:




  • 我不喜欢覆盖一个必须调用 super 的方法。

  • 我不喜欢覆盖私有方法



2。覆盖 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 ... .get('name'));
},

unlink:function(){
AppEvents.off(null,null,this);
}
});

var Users = Backbone.Collection.extend({
model:User,

cleanUp:function(data){
this.each (model){model.unlink();});
this.reset(data);
}
});


//测试
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)不仅被用户集合保留,而且还用于 AppEvents 正在观察的对象。看起来像程序员视角的事件链接听到 - > to - >被侦听的对象的对象,但事实上完全相反:收听 - >到 - >正在收听的对象



现在,如果我们使用 Collection.reset()清空我们看到的集合,因为用户链接已被删除,但 AppEvents 链接仍然存在: p>



用户链接已经消失,还有链接 OurModel.collection 我认为是 Collection._removeReference()作业的一部分。



当我们使用我们的集合.cleanUp()方法对象从内存中消失,我无法使 Chrome.profile 工具明确告诉我对象@ 314019已被删除,但我可以看到它不再存在内存对象


in backbone we have an app that uses an event Aggregator, located on the window.App.Events now, in many views, we bind to that aggregator, and i manually wrote a destroy function on a view, which handles unbinding from that event aggregator and then removing the view. (instead of directly removing the view).

now, there were certain models where we needed this functionality as well, but i can't figure out how to tackle it.

certain models need to bind to certain events, but maybe i'm mistaken but if we delete a model from a collection it stays in memory due to these bindings to the event aggregator which are still in place.

there isn't really a remove function on a model, like a view has. so how would i tacke this?

EDIT on request, some code example.

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');

});​

view this code in action on jsFiddle (output in the console): http://jsfiddle.net/saelfaer/szvFY/1/

as you can see, i don't bind to the events on the model, but to an event aggregator. unbinding events from the model itself, is not necessary because if it's removed nobody will ever trigger an event on it again. but the eventAggregator is always in place, for the ease of passing events through the entire app.

the code example shows, that even when they are removed from the collection, they don't live in the house anymore, but still execute the hide command when a burglar enters the house.

解决方案

I see that even when the binding event direction is this way Object1 -> listening -> Object2 it has to be removed in order to Object1 lost any alive reference.

And seeing that listening to the Model remove event is not a solution due it is not called in a Collection.reset() call then we have two solutions:

1. Overwrite normal Collection cleanUp

As @dira sais here you can overwrite Collection._removeReference to make a more proper cleaning of the method.

I don't like this solutions for two reasons:

  • I don't like to overwrite a method that has to call super after it.
  • I don't like to overwrite private methods

2. Over-wrapping your Collection.reset() calls

Wich is the opposite: instead of adding deeper functionality, add upper functionality.

Then instead of calling Collection.reset() directly you can call an implementation that cleanUp the models before been silently removed:

cleanUp: function( data ){
  this.each( function( model ) { model.unlink(); } );
  this.reset( data );
} 

A sorter version of your code can looks like this:

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)

Check the jsFiddle.

Update: Verification that the Model is removed after remove the binding-event link

First thing we verify that Object1 listening to an event in Object2 creates a link in the direction Obect2 -> Object1:

In the above image we see as the Model (@314019) is not only retained by the users collection but also for the AppEvents object which is observing. Looks like the event linking for a programmer perspective is Object that listen -> to -> Object that is listened but in fact is completely the opposite: Object that is listened -> to -> Object that is listening.

Now if we use the Collection.reset() to empty the Collection we see as the users link has been removed but the AppEvents link remains:

The users link has disappear and also the link OurModel.collection what I think is part of the Collection._removeReference() job.

When we use our Collection.cleanUp() method the object disappear from the memory, I can't make the Chrome.profile tool to explicitly telling me the object @314019 has been removed but I can see that it is not anymore among the memory objects.

这篇关于Backbone.js:如何解除事件的绑定,在模型删除的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆