Backbone View event not firing after upgrading Bac

2019-05-21 14:27发布

问题:

I have upgraded my web application from Backbone 0.9.10 to Backbone 1.2.1, and everything is great with one exception. See the code below:

define( ['underscore', 'backbone', 'text!templates/myResults.html'], function (_, Backbone, Template) {

  var myView = Backbone.View.extend({

    el: '#myResults',

    initialize: function (options) {
        this.targetLoc = options.targetLoc;         
    },

    events: function() {            
        var _events = {};
        _events ['show ' + this.targetLoc + ' a'] = 'tabClicked';           
        return _events;
    },

    tabClicked: function (e) {
        ....stuff....
    }

    template:  _.template(Template),

    render: function() {
        var outputHTML = this.template({model: this.model.toJSON()});
        this.$el.append(outputHTML);
        return this;
    }   

  });

});

return myView;

Before I upgraded Backbone, my tabClicked event fired without issue. Now it doesn't fire, and when I console.log(this.targetLoc); in the events function it says that this.targetLoc is undefined.

I even tried adding:

this.events['show ' + this.targetLoc + ' a'] = 'tabClicked';

to the initialize function to no avail.

This application is using:

  • jQuery 1.9.1
  • jQuery UI 1.10.3
  • Underscore 1.8.3
  • Bootstrap JS 2.3.1
  • Require 2.1.5
  • Backbone 1.2.1 (formerly 0.9.10)

Obviously something changed from 0.9 to 1.2 of Backbone, any ideas on how I can fix my problem?

回答1:

As per the changelog, in 1.2.0 there was a change to how views delegate their events

Views now always delegate their events in setElement. You can no longer modify the events hash or your view's el property in initialize.

So you can no longer rely on attributes you've set in initialize to dynamically create your event hash. However, there's also a constructor that you can use.

A quick demo on plunker shows that this works with 1.2.2.

var MyView = Backbone.View.extend({
  constructor: function(options) {
    this.eventTarget = options.eventTarget;
    Backbone.View.apply(this, arguments);
  },
  events: function() {
    var _events = {};
    _events['click ' + this.eventTarget] = 'clicked';
    return _events;
  },
  clicked: function(e) {
    console.log(e);
  },
  render: function() {
    this.$el.html('<a class="foo">click</a>');
  }
});

Basically you should be able to work around this change by moving the logic that events rely on into the constructor instead of doing it in initialize. The only caveat is that you must remember to call the original constructor of Backbone.View.

So try to replace your initialize with

constructor: function (options) {
    this.targetLoc = options.targetLoc;
    Backbone.View.apply(this, arguments);         
},