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. Let's modify the html:
这里'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>
... 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! What did I expect to get? The template object! Or maybe the data context, but it's neither. However, inside the callbacks (e.g. Template.scores.rendered = function(){ ... }) the context of "this" is always the template instance.
现在,如果单击跨度,您会记录什么? Window对象!我期望得到什么?模板对象!或者也许是数据上下文,但它们都不是。但是,在回调内部(例如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!
谢谢!
2 个解决方案
#1
27
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. But sometimes the data context is undefined
. When you use the Function.prototype.call(thisArg, ...)
in JavaScript, if the thisArg is undefined (e.g. a dataContext is undefined) the browser will set this
equal to window. 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.
事件处理程序中的thisArg应指向数据上下文。但有时数据上下文是不确定的。当您在JavaScript中使用Function.prototype.call(thisArg,...)时,如果未定义thisArg(例如,未定义dataContext),浏览器将其设置为等于window。因此,文档本身并没有错,但事件处理代码无法防止数据上下文未定义的可能性。我猜这将在短期内修复。
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. 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.
那么,什么产生模板的数据上下文?通常,您的根模板甚至不会有数据上下文。换句话说,在没有对象的情况下调用Template函数。但是如果使用{{#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>
#2
13
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!");
}
});
#1
27
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. But sometimes the data context is undefined
. When you use the Function.prototype.call(thisArg, ...)
in JavaScript, if the thisArg is undefined (e.g. a dataContext is undefined) the browser will set this
equal to window. 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.
事件处理程序中的thisArg应指向数据上下文。但有时数据上下文是不确定的。当您在JavaScript中使用Function.prototype.call(thisArg,...)时,如果未定义thisArg(例如,未定义dataContext),浏览器将其设置为等于window。因此,文档本身并没有错,但事件处理代码无法防止数据上下文未定义的可能性。我猜这将在短期内修复。
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. 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.
那么,什么产生模板的数据上下文?通常,您的根模板甚至不会有数据上下文。换句话说,在没有对象的情况下调用Template函数。但是如果使用{{#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>
#2
13
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!");
}
});