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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/15137206/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-26 23:38:37  来源:igfitidea点击:

The context of "this" in Meteor template event handlers (using Handlebars for templating)

javascriptmeteorhandlebars.js

提问by Konstantin K

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"
  • 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 argumentto the event handler will be the data contextof the element that triggered the event."
  • 在模板实例文档部分 ( http://docs.meteor.com/#template_inst) 中提到“模板实例对象在创建、渲染和销毁的模板回调中作为this 的值被发现,并作为一个事件处理程序的参数
  • 在模板部分 ( 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.

现在,如果您单击跨度,您会得到什么记录?窗口对象!我期望得到什么?模板对象!或者可能是数据上下文,但两者都不是。然而,在回调内部(例如 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?
  • slightly incomplete documentation on the templates?
  • me completely misinterpreting the docs or not understanding something fundamental about Meteor or Handlebars?
  • Handlebars、Meteor 或介于两者之间的错误?
  • 关于模板的文档有点不完整?
  • 我完全误解了文档或不了解有关 Meteor 或 Handlebars 的一些基本知识?

Thanks!

谢谢!

采纳答案by cmather

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 shouldpoint 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 thisequal to window. So, the docs aren't wrongper 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应该指向数据上下文。但有时数据上下文是undefined. 当您Function.prototype.call(thisArg, ...)在 JavaScript 中使用 the时,如果 thisArg 未定义(例如 dataContext 未定义),浏览器将设置为this等于 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 {{#withblock helper or the {{#eachiterator, a data context will be created for each item in the list, or in the case of the withhelper, the object.

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

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>

回答by Brandon Meyer

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