我正在尝试将一个按键事件分配给for循环中的元素。我知道在for循环中动态分配事件存在问题,我已经解决了“click”事件的问题,但我对它如何适用于keypress感到茫然。 (可能是因为我真的不明白“点击”是如何开始的......关闭避免不是我完全得到的)
基本设置是有一个for循环,它将打印出许多不同的textareas和它们下面的div。按div将文本区域中的文本发送给正确的人。我希望发生的是,如果在文本区域内按下回车按钮,则应发送相同的消息。
for( var i in people){
var message = $('<textarea></textarea>').appendTo(container);
message.on( "keypress", function(e) {
if(e.keyCode==13){
// code does make it in here ...
sendMessage(people[i].name); // but this never gets run
}
});
var messageButton= $('<div>Send</div>').appendTo(container);
messageButton.on( "click", sendMessage(people[i].name) );
}
var sendMessage = function(to) {
return function(){
/* do the sending of the message to the right person */
}
}
任何人都可以帮我理解以下内容吗?
为什么点击功能首先起作用?我不明白为什么我们必须在功能块周围放回。
为什么按键功能不起作用?
在更一般的层面上,keypress如何开始工作。函数(e)不应该起作用,因为'e'不是什么东西,甚至设置在哪里?
答案 0 :(得分:0)
代码中keypress
的问题在于,它始终会将消息发送给人员中的最新人员,因为执行该消息时,i
将包含最新值。< / p>
我可能会使用forEach
代替:
people.forEach(function (person) {
var message = $('<textarea></textarea>').appendTo(container);
// you can use keypress - http://api.jquery.com/keypress/#keypress-eventData-handler
// see the examples in the reference
message.keypress(function (e) {
if (e.which === 13) {
// here you should invoke the function returned by the sendMessage
sendMessage(person.name)();
}
});
var messageButton= $('<div>Send</div>').appendTo(container);
messageButton.click(sendMessage(person.name));
});
使用这种方法,您不需要将函数包装在sendMessage中,只需在相应的事件处理程序中调用原始函数。
答案 1 :(得分:0)
使用jQuery清理示例。您应该阅读有关jQuery和迭代闭包的更多信息,以便您可以轻松了解正在发生的事情。
$.each(people, function (person) {
var $message = $('<textarea></textarea>').appendTo(container);
var $button = $('<div>Send</div>').appendTo(container);
var send = sendMessage(person.name);
// Keypress handler
$message.keypress(function (e) {
if (e.which === 13) { // on enter do the following
send();
}
});
$button.click(send);
});
答案 2 :(得分:0)
这是使用手写封闭的另一种解决方案:
var people = {
'p1': {
name: 'john'
},
'p2': {
name: 'bob'
},
'p3': {
name: 'jim'
}
};
var container = $('#container');
for (var i in people) {
(function (name) {
var message = $('<textarea></textarea>').appendTo(container);
message.keypress(function (e) {
if (e.keyCode == 13) {
sendMessage(name);
}
});
var messageButton = $('<div>Send</div>').appendTo(container);
messageButton.click(function () {
sendMessage(name)
});
})(people[i].name);
}
function sendMessage(to) {
console.log(to);
}
正如其他人所说的那样,问题在于该事件与最后一次引用“i”相关联。在循环。使用闭包解决了这个问题,同时仍然允许你使用for..in循环。
另外需要注意的是,如果在绑定后没有动态地将这些元素附加到DOM ,则没有理由使用jquery的.on()。您可以直接将.keypress()和.click()处理程序绑定到元素上,如我的小提琴和@AlexAtNet的答案所示。
但它很笨重,我会像其他人已经建议的那样使用jquerys $ .each。