Meteor模板事件处理程序中的“this”的上下文(使用Handlebars进行模板化)
关于meteor模板事件处理程序(带把手)的一个简短的问题。
- 在模板实例的文档部分( http://docs.meteor.com/#template_inst )中提到“ 模板实例对象在创build,渲染和销毁的模板callback中作为这个值被find, 争论事件处理程序 “
- 在“模板”部分( http://docs.meteor.com/#templates )中,它说:“ 最后,您可以在模板函数上使用事件声明来设置事件处理程序的表格。事件处理程序的这个参数将是触发事件的元素的数据上下文 。 “
那么这只是部分的事实。 我们使用文档中的示例:
<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">YU 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); } });
现在,如果你点击跨度,你会得到什么logging? 窗口对象! 我期望得到什么? 模板对象! 或者可能是数据上下文,但它不是。 但是,在callback(例如Template.scores.rendered = function(){…})中,“this”的上下文始终是模板实例。
我想我真正的问题是:这是有关的事情
- Handlebars,Meteor或其他地方的错误?
- 在模板上稍微不完整的文档?
- 我完全误解了文档,或者不了解meteor或把手的基本知识?
谢谢!
这个video解释了这些概念:
http://www.eventedmind.com/posts/meteor-spark-data-annotation-and-data-contexts 。
直接回答你的问题:
事件处理程序中的thisArg 应指向数据上下文。 但有时数据上下文是undefined
。 当您在JavaScript中使用Function.prototype.call(thisArg, ...)
时,如果thisArg未定义(例如dataContext未定义),则浏览器将设置为等于窗口。 所以,文档本身并没有错 ,但是事件处理代码并没有防范数据上下文未定义的可能性。 我猜这将在短期内得到修复。
那么,为模板产生一个数据上下文是什么呢? 通常你的根模板甚至没有数据上下文。 换句话说,模板函数在没有对象的情况下被调用。 但是,如果使用{{#with
块帮助器或{{#each
迭代器,将为列表中的每个项目创build一个数据上下文,或者在带有帮助器的情况下创build该对象。
例:
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>
函数中的第一个参数是事件。 所以你可以使用事件的目标来抓住你的元素。
Template.scores.events({ 'click .click-me': function (event, template) { console.log(event.target); $(event.target).text("O but I did!"); } });