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

Posted

技术标签:

【中文标题】Meteor 模板事件处理程序中“this”的上下文(使用 Handlebars 进行模板)【英文标题】:The context of "this" in Meteor template event handlers (using Handlebars for templating) 【发布时间】:2013-02-14 17:49:18 【问题描述】:

关于 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?

谢谢!

【问题讨论】:

这是一个正确的问题。我一直使用function(event,template) 访问事件中的数据,然后通过template.data 希望我能投票两次 @ТаняТ。您可以像我一样将问题标记为收藏 ;-) 【参考方案1】:

此视频解释了这些概念:

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

直接回答你的问题:

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

那么,什么会为模板生成数据上下文?通常,您的根模板甚至没有数据上下文。换句话说,模板函数在没有对象的情况下被调用。但是,如果您使用 #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>

【讨论】:

如果数据上下文未定义,则数据上下文设置为 window 已在最新版本的 Meteor 中修复。所以,现在事件处理程序中的this 总是指向一个对象,要么是数据上下文,要么是一个空对象(如果没有数据上下文)。 感谢您提出 :-)。 我刚刚更新到 0.5.9,如果没有设置数据上下文,我仍然会得到 Window...我错过了什么吗? 更新:是的,我是。事件处理程序中的“this”现在始终是一个对象(如果没有数据上下文,则为空)。但是,除非设置了数据上下文,否则它仍然是 Window inside helpers... 啊,错过了。我将打开一个 Github 问题。【参考方案2】:

函数中的第一个参数是事件。所以你可以使用事件的目标来抓取你的元素。

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

【讨论】:

谢谢布兰登。这确实是获取元素的一种方法(尽管我通常会使用 currentTarget)。但是它没有回答我的问题:错误、文档还是我? 我会说文档。特别是因为流星仍然是预发布。文档可能是最难保持最新和完全包容的东西。在这样的情况下,我只是开始向函数添加参数,然后控制台记录它们。例如函数 (param1, param2, param3) console.log(param1);控制台.log(param2); console.log(param3); 您可以使用 console.log(arguments) 一次性获取所有内容。

以上是关于Meteor 模板事件处理程序中“this”的上下文(使用 Handlebars 进行模板)的主要内容,如果未能解决你的问题,请参考以下文章

为啥 Meteor 模板助手不在上下文中返回变量?

在 Meteor 的模板渲染函数中访问父数据上下文

功能组件的子事件处理程序中的'this'上下文

在模板上下文中从另一个助手调用一个助手 (Meteor 0.9.4)

如何将 this 上下文传递给事件处理程序?

Meteor:检测嵌套模板中的事件