42

关于 Meteor 中模板的事件处理程序上下文的快速问题(使用 Handlebars)。

  • 在关于模板实例的文档部分 ( http://docs.meteor.com/#template_inst ) 中提到“模板实例对象在创建、渲染和销毁的模板回调中作为 this 的值找到,并且作为事件处理程序的参数
  • 在模板部分 ( 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);
  }
});

现在,如果您单击跨度,您会记录什么?窗口对象!我期望得到什么?模板对象!或者可能是数据上下文,但两者都不是。然而,在回调内部(例如 Template.scores.rendered = function(){ ... }),“this”的上下文始终是模板实例。

我想我真正的问题是:这与

  • Handlebars、Meteor 或介于两者之间的某个错误?
  • 模板上的文档稍微不完整?
  • 我完全误解了文档或不了解 Meteor 或 Handlebars 的基本知识?

谢谢!

4

2 回答 2

27

该视频解释了这些概念:

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

直接回答你的问题:

事件处理程序中的 thisArg指向数据上下文。但有时数据上下文是undefined. 当您Function.prototype.call(thisArg, ...)在 JavaScript 中使用时,如果 thisArg 未定义(例如 dataContext 未定义),浏览器将设置this为等于 window。因此,文档本身并没有,但事件处理代码并没有防止数据上下文未定义的可能性。我猜这将在短期内修复。

那么,是什么产生了模板的数据上下文?通常,您的根模板甚至没有数据上下文。换句话说,模板函数在没有对象的情况下被调用。但是,如果您使用{{#with块助手或{{#each迭代器,将为列表中的每个项目创建数据上下文,或者在使用助手的情况下为对象创建数据上下文。

例子:

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>
于 2013-03-01T02:50:09.377 回答
13

函数中的第一个参数是事件。因此,您可以使用事件的目标来获取您的元素。

Template.scores.events({
  'click .click-me': function (event, template) {
    console.log(event.target);
    $(event.target).text("O but I did!");
  }
});
于 2013-02-28T16:23:57.417 回答