Backbonejs:.on vs .listenTo vs .bind

lau*_*kok 14 javascript callback backbone.js

有什么区别.on,.listenTo,和.bind?

我在这里测试了它们,它们看起来做同样的事情:回调.

var NewStatusView = Backbone.View.extend({

    events: {
        "submit form": "addStatus"
    },

    initialize: function(options) {

        // using .on
        //this.collection.on("add", this.clearInput, this);

        // or using bind: 
        //_.bindAll(this, 'addStatus', 'clearInput');
        //this.collection.bind('add', this.clearInput);

        // or using listenTo: 
         _.bindAll(this, 'addStatus', 'clearInput');
        this.listenTo(this.collection, 'add', this.clearInput) ;
    },

    addStatus: function(e) {
        e.preventDefault();
        this.collection.create({ text: this.$('textarea').val() });
    },

    clearInput: function() {
        this.$('textarea').val('');
    }
});
Run Code Online (Sandbox Code Playgroud)

什么时候使用哪种情况最好?

Aus*_*tin 22

通常最好使用 listenTo()

来自Addy Osmani的Backbone Essentials:

虽然on()与off()直接添加回调的观察对象, listenTo()讲述了一个对象监听另一个对象的事件,让听者跟踪为它正在监听的事件.stopListening()随后可以在监听器上调用它来告诉它停止监听事件:

var a = _.extend({}, Backbone.Events);
var b = _.extend({}, Backbone.Events);
var c = _.extend({}, Backbone.Events);

// add listeners to A for events on B and C
a.listenTo(b, 'anything', function(event){ console.log("anything happened"); });
a.listenTo(c, 'everything', function(event){ console.log("everything happened"); });

// trigger an event
b.trigger('anything'); // logs: anything happened

// stop listening
a.stopListening();

// A does not receive these events
b.trigger('anything');
c.trigger('everything');
Run Code Online (Sandbox Code Playgroud)

如果您使用on和off并同时删除视图及其相应的模型,通常没有问题.但是,当您删除已注册为模型上的事件通知的视图时,会出现问题,但您不删除模型或调用以删除视图的事件处理程序.由于模型具有对视图的回调函数的引用,因此JavaScript垃圾收集器无法从内存中删除视图.这被称为ghost视图,并且是一种常见的内存泄漏形式,因为模型通常倾向于在应用程序的生命周期中超过相应的视图.有关该主题和解决方案的详细信息,请查看Derick Bailey撰写的这篇优秀文章.

实际上,每个on调用一个对象也需要调用一个对象off,以便垃圾收集器完成它的工作.listenTo() 更改,允许视图绑定到模型通知,并通过一次调用解除所有这些通知的绑定 - stopListening().

默认实现View.remove()调用 stopListening(),确保listenTo() 在视图被销毁之前绑定使用的任何侦听器都是未绑定的.

var view = new Backbone.View();
var b = _.extend({}, Backbone.Events);

view.listenTo(b, 'all', function(){ console.log(true); });
b.trigger('anything');  // logs: true

view.listenTo(b, 'all', function(){ console.log(false); });
view.remove(); // stopListening() implicitly called
b.trigger('anything');  // does not log anything
Run Code Online (Sandbox Code Playgroud)

  • 我没有upvote,因为没有提到绑定!我不关心bind的使用,因为与_.bind和_.bindAll有心理命名空间冲突,为什么Jeremy你也为事件选择了bind (3认同)