42 votes

Le contexte de "this" dans les gestionnaires d'événements de modèles Meteor (à l'aide de Handlebars pour la création de modèles)

Une petite question sur le contexte des gestionnaires d'événements pour les modèles dans Meteor (le Guidon).

  • Dans la section de la Documentation sur les instances de modèle (http://docs.meteor.com/#template_inst), il est mentionné que "leModèle, les objets sont trouvés que la valeur de cette dans le, rendus, et détruit modèle de rappels et comme un argument de gestionnaires d'événements"
  • Dans la section Modèles (http://docs.meteor.com/#templates), il dit:"Enfin, vous pouvez utiliser un des événements de la déclaration sur une fonction de modèle pour créer un tableau des gestionnaires d'événements. Le format est documenté à Cartes d'Événement. Cet argument de l'événement seront le contexte de données de l'élément qui a déclenché l'événement."

Eh bien, ce n'est que partiellement vrai. Nous allons utiliser un exemple tiré de la doc:

<template name="scores">
  {{#each player}}
    {{> playerScore}}
  {{/each}}
</template>

<template name="playerScore">
  <div>{{name}}: {{score}}
    <span class="givePoints">Give points</span>
  </div>
</template
Template.playerScore.events({
  'click .givePoints': function () {
    Users.update({_id: this._id}, {$inc: {score: 2}});
  });

Ici, le "ce" contexte de la " cliquez sur .givePoints' gestionnaire d'événement est en effet le modèle de l'instance de playerScore. Nous allons modifier le code html:

<template name="scores">
  <span class="click-me">Y U NO click me?<span>
  {{#each player}}
    {{> playerScore}}
  {{/each}}
</template>

<template name="playerScore">
  <div>{{name}}: {{score}}
    <span class="givePoints">Give points</span>
  </div>
</template>

... et ajouter un gestionnaire d'événements pour .cliquez sur-moi sur les scores de modèle:

Template.scores.events({
  'click .click-me': function () {
    console.log(this);
  }
});

Maintenant, si vous cliquez sur la durée, qu'obtenez-vous connecté? L'objet de la Fenêtre! Qu'ai-je espérer obtenir? L'objet de modèle! Ou peut-être le contexte de données, mais il est ni. Cependant, à l'intérieur de l'rappels (par exemple, Modèle.les scores.rendus = function(){ ... }) le contexte de la "ce" est toujours le modèle de l'instance.

Je suppose que ma question serait plutôt: est-ce quelque chose à faire avec

  • un bug dans le Cintre, le Météore, ou quelque part entre les deux?
  • légèrement incomplète de la documentation sur les modèles?
  • moi complètement mauvaise interprétation de la documentation ou de ne pas comprendre quelque chose de fondamental de Météore, ou le Guidon?

Merci!

27voto

cmather Points 1418

Cette vidéo explique les concepts:

http://www.eventedmind.com/posts/meteor-spark-data-annotation-and-data-contexts.

La réponse directe à votre question:

Le thisArg à l'intérieur d'un gestionnaire d'événement doit pointer vers un contexte de données. Mais parfois, le contexte de données est - undefined. Lorsque vous utilisez l' Function.prototype.call(thisArg, ...) en JavaScript, si le thisArg est pas défini (par exemple, un dataContext est pas défini) le navigateur mettra this égal à la fenêtre. Ainsi, les docs ne sont pas mauvais en soi, mais le code de gestion des événements n'est pas la protection contre la possibilité d'un contexte de données défini. Je devine qui sera fixé dans l'ordre court.

Donc, ce qui produit un contexte de données pour un modèle? Normalement à la racine de votre modèle n'aurez même pas un contexte de données. En d'autres termes, le Modèle de la fonction est appelée sans objet. Mais si vous utilisez l' {{#with bloc aide ou de l' {{#each itérateur, un contexte de données sera créé pour chaque élément dans la liste, ou dans le cas de la avec l' aide de l'objet.

Exemple:

var context = {};

<template name="withHelper">
  {{#with context}}
    // data context is the context object
  {{/with}}
</template>

var list = [ {name: "one"}, {name: "two"} ];

<template name="list">
  {{#each list}}
    {{ > listItem }} // data context set to the list item object
  {{/each}}
</template>

13voto

Brandon Meyer Points 155

Le premier paramètre de la fonction est l'événement. Vous pouvez donc utiliser la cible de l'événement pour saisir votre élément.

 Template.scores.events({
  'click .click-me': function (event, template) {
    console.log(event.target);
    $(event.target).text("O but I did!");
  }
});
 

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X