J'apprends backbone.js, et je me sens confus à ce sujet: je suis en train de suivre le didacticiel: http://arturadib.com/hello-backbonejs/
Comme vous pouvez le voir dans le premier exemple (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);
Mais si je commente la phrase: _.bindAll(this, 'render');
, Cela va toujours fonctionner. J'ai cherché dans google et quelqu'un a dit que la méthode bindAll()
est nécessaire puisque si j'ai changé mon contexte, l'appel de this.render
peut ne pas être disponible. Je me sens confus sur le «contexte». Et peut-on aussi m'expliquer quand l'appel ( this.render
) ne sera pas disponible?
Pour l'exemple que vous avez donné _.bindAll(this, 'render');
_bindAll()
pas nécessaire, mais si vous avez des fonctions de rappel où this
peut être changé en contexte d'autre chose, alors _bindAll()
peut être pratique.
Par exemple:
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 */ }
bindAll
fragment:
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 utilise simplement des flèches CoffeeScript et graisse et résolvez-le proprement au niveau de la langue.
Dans ce cas, vous n'avez pas besoin de _.bindAll
, mais disons que votre vue comporte une méthode qui provoque un redistributeur et que vous faites quelque chose comme ceci:
.., myMethod: function() { this.$('.someselector').change(this.render); },
Si vous n'avez pas _.bindAll
pour render
, votre contexte serait désactivé.
Regardons _.bindAll
ce que _.bindAll
fait de underscore.js documents officiels .
_.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; };
Ce qu'il fait, c'est de lier automatiquement toutes ses fonctions à son contexte correct. (Où sa fonction est déclarée plutôt que invoquée.
Personnellement, je pense que c'était une convention pour l'ancienne version de Backbone.js pour lier ses events
, ou les auditeurs d'action DOM. Étant donné que les nouvelles versions de Backbone View
lient automatiquement et délient les auditeurs dans les events
. Trouvez plus par recherche Binding "this"
ici
J'espère que cela vous aidera.