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;
  };

それが行うことは、すべての関数を正しいコンテキストに自動的にバインドすることです。(その関数は、呼び出されるのではなく宣言されます。

events個人的には、古いバージョンの Backbone.js がDOM アクション リスナーをバインドするのは慣習だったと思います。新しいバージョン以降、BackboneViewは でリスナーを自動的にバインドおよびバインド解除しeventsます。検索でもっと探すBinding "this" はこちら

お役に立てば幸いです。

于 2015-07-14T06:52:18.007 に答える