web-dev-qa-db-ja.com

Meteorテンプレートイベントハンドラーの「this」のコンテキスト(テンプレートにHandlebarを使用)

Meteor(with Handlebars)のテンプレートのイベントハンドラーのコンテキストに関する簡単な質問。

  • テンプレートインスタンスに関するドキュメントのセクション( http://docs.meteor.com/#template_inst )には、「テンプレートインスタンスオブジェクトがこれは、作成、レンダリング、および破棄されたテンプレートコールバック、およびイベントハンドラーへの引数として "
  • [テンプレート]セクション( http://docs.meteor.com/#templates )では、「最後に、テンプレート関数でイベント宣言を使用してセットアップできますイベントハンドラの表形式はイベントマップに記載されていますイベントハンドラへのthis引数イベントをトリガーした要素のデータコンテキスト "

まあ、これは部分的に真実です。ドキュメントの例を使用してみましょう。

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

ここで、「click .givePoints」イベントハンドラの「this」コンテキストは、実際にはplayerScoreのテンプレートインスタンスです。 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>

...スコアテンプレートに.click-meのイベントハンドラーを追加します。

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

スパンをクリックすると、何が記録されますか? Windowオブジェクト!何を期待していましたか?テンプレートオブジェクト!または、データコンテキストかもしれませんが、どちらでもありません。ただし、コールバック(例:Template.scores.rendered = function(){...})内では、「this」のコンテキストは常にテンプレートインスタンスです。

私の本当の質問は次のようになると思います:これは何か

  • handlebars、Meteor、またはその中間のバグ?
  • テンプレートに関するドキュメントが少し不完全ですか?
  • ドキュメントを完全に誤解したり、MeteorやHandlebarsの基本的なことを理解していないのですか?

ありがとう!

42
Konstantin K

このビデオでは、概念について説明します。

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

あなたの質問への直接的な答え:

イベントハンドラー内のthisArgshouldはデータコンテキストを指します。ただし、データコンテキストがundefinedである場合があります。 JavaScriptでFunction.prototype.call(thisArg, ...)を使用する場合、thisArgが未定義(たとえば、dataContextが未定義)の場合、ブラウザはthisをwindowと等しく設定します。したがって、ドキュメント自体はwrongではありませんが、イベント処理コードは、データコンテキストが未定義になる可能性を保護していません。私はそれがすぐに修正されると推測しています。

では、何がテンプレートのデータコンテキストを生成しますか?通常、ルートテンプレートにはデータコンテキストさえありません。つまり、テンプレート関数はオブジェクトなしで呼び出されます。ただし、{{#withブロックヘルパーまたは{{#eachイテレータ、リスト内の各アイテム、またはwithヘルパーの場合はオブジェクトのデータコンテキストが作成されます。

例:

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

関数の最初のパラメーターはイベントです。そのため、イベントのターゲットを使用して要素を取得できます。

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