简体   繁体   English

Meteor模板事件处理程序中“this”的上下文(使用Handlebars进行模板化)

[英]The context of “this” in Meteor template event handlers (using Handlebars for templating)

A quick question on the context of the event handlers for templates in Meteor (with Handlebars). 关于Meteor中模板事件处理程序(带Handlebars)的上下文的快速问题。

  • In the section of Documentation on template instances ( http://docs.meteor.com/#template_inst ) it is mentioned that " Template instance objects are found as the value of this in the created, rendered, and destroyed template callbacks and as an argument to event handlers " 在关于模板实例的文档部分( http://docs.meteor.com/#template_inst )中,提到“ 在创建,呈现和销毁的模板回调中找到模板实例对象作为其值,并作为事件处理程序的参数
  • In the Templates section ( http://docs.meteor.com/#templates ) it says " Finally, you can use an events declaration on a template function to set up a table of event handlers. The format is documented at Event Maps. The this argument to the event handler will be the data context of the element that triggered the event. " 在“模板”部分( http://docs.meteor.com/#templates )中,它说“ 最后,您可以在模板函数上使用事件声明来设置事件处理程序表。格式记录在事件映射中。事件处理程序的this参数将是触发事件的元素的数据上下文

Well, this is only partially true. 嗯,这只是部分正确。 Let's use an example from the docs: 让我们使用文档中的示例:

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

Here the "this" context of the 'click .givePoints' event handler is indeed the template instance of playerScore. 这里'click .givePoints'事件处理程序的“this”上下文确实是playerScore的模板实例。 Let's modify the html: 我们来修改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>

... and add an event handler for .click-me on the scores template: ...并在分数模板上为.click-me添加事件处理程序:

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

Now, if you click the span, what do you get logged? 现在,如果单击跨度,您会记录什么? The Window object! Window对象! What did I expect to get? 我期望得到什么? The template object! 模板对象! Or maybe the data context, but it's neither. 或者也许是数据上下文,但它们都不是。 However, inside the callbacks (eg Template.scores.rendered = function(){ ... }) the context of "this" is always the template instance. 但是,在回调内部(例如Template.scores.rendered = function(){...}),“this”的上下文始终是模板实例。

I guess my real question would be: is this something to do with 我想我真正的问题是:这是否与此有关

  • a bug in Handlebars, Meteor or somewhere in between? Handlebars,Meteor或介于两者之间的错误?
  • slightly incomplete documentation on the templates? 模板上的文档略有不完整?
  • me completely misinterpreting the docs or not understanding something fundamental about Meteor or Handlebars? 我完全曲解了文档或者没有理解Meteor或Handlebars的基本内容?

Thanks! 谢谢!

This video explains the concepts: 该视频解释了这些概念:

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

The direct answer to your question: 直接回答你的问题:

The thisArg inside an event handler should point to a data context. 事件处理程序中的thisArg 指向数据上下文。 But sometimes the data context is undefined . 但有时数据上下文是undefined When you use the Function.prototype.call(thisArg, ...) in JavaScript, if the thisArg is undefined (eg a dataContext is undefined) the browser will set this equal to window. 当您使用Function.prototype.call(thisArg, ...)在JavaScript中,如果thisArg是不确定的(例如,一个DataContext是不确定的),浏览器会设置this等于窗口。 So, the docs aren't wrong per se but the event handling code isn't guarding against the possibility of a data context being undefined. 因此,文档本身并没有 ,但事件处理代码无法防止数据上下文未定义的可能性。 I'm guessing that will be fixed in short order. 我猜这将在短期内修复。

So, what produces a data context for a template? 那么,什么产生模板的数据上下文? Normally your root template won't even have a data context. 通常,您的根模板甚至不具有数据上下文。 In other words, the Template function is called without an object. 换句话说,在没有对象的情况下调用Template函数。 But if you use the {{#with block helper or the {{#each iterator, a data context will be created for each item in the list, or in the case of the with helper, the object. 但是如果使用{{#with块帮助器或{{#each迭代器,将为列表中的每个项创建数据上下文,或者对于with helper,则为对象。

Example: 例:

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>

The first parameter in the function is the event. 函数中的第一个参数是事件。 So you could use the target of the event to grab your element. 因此,您可以使用事件的目标来获取元素。

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM