Backbone - Anyway to check if an event has been bo

2019-08-13 02:26发布

问题:

I'm doing this inside one of my Views:

render: function($options) {
    ...

    this.collection.on('reset', _(function() {
        this.render($options);
    }).bind(this));

    ....
}

The problem is, whenever reset as well as the re-rendering has been triggered, a new reset binding will be created, resulting 2x, 4x, 8x, etc. times of re-rendering as it goes on.

It's a bit tricky to move the binding into the initialize section (which should solve this issue), however since it's not an option, is there any other solution available, like having Backbone checking if this event has been bound before, or something?

回答1:

Moving your binding to initialize would be best but assuming that you have good reasons not to, you could just set a flag:

initialize: function() {
    var _this = this;
    this._finish_initializing = _.once(function($options) {
        _this.collection.on('reset', function() {
            _this.render($options);
        });
    });
    //...
},
render: function($options) {
    this._finish_initializing($options);
    //...
}

There are lots of different ways to implement the flag, _.once just nicely hides the flag checking. You could also trigger an event in render have a listener that unbinds itself:

initialize: function() {
    var finish_initializing = function($options) {
        /* your binding goes here ... */
        this.off('render', finish_initializing);
    };
    this.on('render', finish_initializing, this);
},
render: function($options) {
    this.trigger('render', $options);
    //...
}

That's the same logic really, just dressed up in different clothes. You could also use an explicit flag and an if in render or assign a function to this._finish in initialize and that function would delete this._finish.



回答2:

like having Backbone checking if this event has been bound before, or something?

Sure..

!!this.collection._events["render"]

Backbone doesn't expose most of the API required to make it useful. That's alright, use it anyway.



回答3:

First, define your event handler function as a named function

var self = this;
var onReset = function() {
    self.render($options);
}

Then, defensively unbind the function each time render is called

this.collection.off('reset', onReset);
this.collection.on('reset', onReset);


回答4:

I recently accomplished this using a javascript variable.

Outside of any functions, I declared:

var boundalready =0

Then, inside the function:

if (boundalready == 0){
      boundalready = 1;
      bind(this);
    };

This worked for me pretty well.