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

Kon*_*n K 42 javascript handlebars.js meteor

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

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

这里'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>
Run Code Online (Sandbox Code Playgroud)

...并在分数模板上为.click-me添加事件处理程序:

Template.scores.events({
  'click .click-me': function () {
    console.log(this);
  }
});
Run Code Online (Sandbox Code Playgroud)

现在,如果单击跨度,您会记录什么?Window对象!我期望得到什么?模板对象!或者也许是数据上下文,但它们都不是.但是,在回调内部(例如Template.scores.rendered = function(){...}),"this"的上下文始终是模板实例.

我想我真正的问题是:这是否与此有关

  • Handlebars,Meteor或介于两者之间的错误?
  • 模板上的文档略有不完整?
  • 我完全曲解了文档或者没有理解Meteor或Handlebars的基本内容?

谢谢!

cma*_*her 27

该视频解释了这些概念:

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

直接回答你的问题:

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

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

例:

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>
Run Code Online (Sandbox Code Playgroud)


Bra*_*yer 13

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

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

  • 谢谢布兰登.这确实是获取元素的一种方法(尽管我通常使用currentTarget).但它没有回答我的问题:bug,docs还是我? (2认同)
  • 我会说文档.埃斯普因为流星还在发布之前.文档可能是最难跟上并完全包容的事情.在这些情况下,我只是开始向函数添加params,然后控制台记录它们.例如function(param1,param2,param3){console.log(param1); 的console.log(参数2); 的console.log(参数3);} (2认同)