22

我正在学习backbone.js,对此感到困惑:我正在关注教程: http ://arturadib.com/hello-backbonejs/

正如您在第一个示例(1.js)中看到的那样:

(function($){
  var ListView = Backbone.View.extend({    
    el: $('body'), // attaches `this.el` to an existing element.

    initialize: function(){
      _.bindAll(this, 'render'); // fixes loss of context for 'this' within methods

       this.render(); // not all views are self-rendering. This one is.
    },

    render: function(){
      $(this.el).append("<ul> <li>hello world</li> </ul>");
    }
  });

  var listView = new ListView();      
})(jQuery);

但是,如果我注释掉这句话:_.bindAll(this, 'render');,这仍然有效。我在谷歌搜索过,有人说该方法bindAll()是必要的,因为如果我切换上下文,调用this.render可能不可用。我对“上下文”感到困惑。this.render当调用 ( ) 将不可用时,也有人可以解释我吗?

4

4 回答 4

29

对于您给出的示例_.bindAll(this, 'render');不是必需的,但如果您有回调函数this可以更改为其他内容的上下文,那么_bindAll()可以很方便。

例如:

initialize: function(){
  _.bindAll(this, 'render', 'clickFunc');
},
events: {
   'click .someElement': 'clickFunc'
},
clickFunc: function(e) {
   /** If you remove the clickFunc from the list of events in bindAll, 
          'this' will refer to the element that invoked the event.

       Adding the clickFunc event in the _.bindAll, ensures that 'this' stays
          as the view.
   */
  this /** <-- our focal point */
}
于 2013-01-25T07:27:56.293 回答
10
  • 在视图的事件哈希中列为属性值的任何方法都会由主干自动为您绑定
  • 您在视图中手动用作模型或集合中的事件处理程序的任何方法都应通过手动绑定bindAll
    • 或者您可以在注册绑定时提供上下文
    • 或者您可以使用 EMCA 5 的function.bind来获得相同的结果

片段:

events: {
    'click .win': 'win',
    'click .lose': 'lose'
},
initialize: function () {
    //win and lose are automatically bound for you
    //because they are in the events property

    //refresh must be manually bound
    this.model.on('change', this.refresh);

    //which you can do ECMA5 style if you like
    this.model.on('change', this.refresh.bind(this));

    //OR you can provide a context backbone style
    this.model.on('change:foo', this.fooChange, this);

    //However, since you pretty much never want an unbound function
    //in a view, you can just stick this in all your initialize methods
    //and call it done
    //Note this will bind all functions in your view class if you don't
    //pass specific method names. I recommend this form.
    _.bindAll(this);
},
win: function () {...},
lose: function () {...},
refresh: function () {...},
fooChange: function() {...}

... OOOOORRRR只需使用 CoffeeScript 和粗箭头并在语言级别上干净地解决这个问题。

于 2013-01-25T02:21:53.137 回答
2

在这种情况下,您不需要_.bindAll,但假设您的视图有一个导致重新渲染的方法,并且您执行以下操作:

..,
myMethod: function() {
    this.$('.someselector').change(this.render);
},

如果您没有_.bindAllfor render,则您的上下文将关闭。

于 2013-01-25T01:59:07.550 回答
2

让我们仔细看看underscore.js 官方文档_.bindAll的作用。

  _.bindAll = function(obj) {
    var i, length = arguments.length, key;
    if (length <= 1) throw new Error('bindAll must be passed function names');
    for (i = 1; i < length; i++) {
      key = arguments[i];
      obj[key] = _.bind(obj[key], obj);
    }
    return obj;
  };

它所做的是自动将其所有功能绑定到其正确的上下文。(它的函数被声明而不是被调用。

我个人认为这是旧版本 Backbone.js 绑定其eventsDOM 动作侦听器的约定。由于新版本 BackboneViewevents. 在这里通过搜索找到更多Binding "this"

我希望它有所帮助。

于 2015-07-14T06:52:18.007 回答