web-dev-qa-db-fra.com

Le contexte de "ceci" dans les gestionnaires d'événements du modèle Meteor (à l'aide des guidons pour les modèles)

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

  • Dans la section de la documentation sur les instances de modèle ( http://docs.meteor.com/#template_inst ), il est mentionné que " les objets d'instance de modèle sont trouvés comme valeur de ceci dans le créé, rendu et détruit les rappels de modèles et comme argument aux gestionnaires d'événements "
  • Dans la section Modèles ( http://docs.meteor.com/#templates ), il est indiqué " Enfin, vous pouvez utiliser une déclaration d'événements sur une fonction de modèle pour configurer une table de gestionnaires d'événements. Le format est documenté dans Event Maps. L'argument this du gestionnaire d'événements sera le contexte de données de l'élément qui a déclenché l'événement. "

Eh bien, ce n'est que partiellement vrai. Prenons un exemple tiré de la documentation:

<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 contexte "this" du gestionnaire d'événements "click .givePoints" est en effet l'instance de modèle de playerScore. Modifions le 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 ajoutez un gestionnaire d'événements pour .click-me sur le modèle de score:

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

Maintenant, si vous cliquez sur la plage, qu'est-ce que vous obtenez connecté? L'objet Window! Qu'espérais-je obtenir? L'objet modèle! Ou peut-être le contexte des données, mais ce n'est ni l'un ni l'autre. Cependant, à l'intérieur des rappels (par exemple Template.scores.rendered = function () {...}) le contexte de "this" est toujours l'instance de modèle.

Je suppose que ma vraie question serait: est-ce quelque chose à voir avec

  • un bug dans le guidon, Meteor ou quelque part entre les deux?
  • documentation légèrement incomplète sur les modèles?
  • -je mal interpréter complètement les documents ou ne pas comprendre quelque chose de fondamental à propos de Meteor ou du guidon?

Merci!

42
Konstantin K

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énements doit pointer vers un contexte de données. Mais parfois, le contexte des données est undefined. Lorsque vous utilisez la Function.prototype.call(thisArg, ...) en JavaScript, si thisArg n'est pas défini (par exemple, un dataContext n'est pas défini), le navigateur définira this égal à la fenêtre. Ainsi, les documents ne sont pas faux en soi, mais le code de gestion des événements ne protège pas contre la possibilité d'un contexte de données non défini. Je suppose que ce sera corrigé dans un court délai.

Alors, qu'est-ce qui produit un contexte de données pour un modèle? Normalement, votre modèle racine n'aura même pas de contexte de données. En d'autres termes, la fonction Template est appelée sans objet. Mais si vous utilisez le {{#with helper bloc ou {{#each itérateur, un contexte de données sera créé pour chaque élément de la liste, ou dans le cas de avec assistant, 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>
27
cmather

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

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