Javascript 在 for 循环中分配点击处理程序
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/4091765/
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
Assign click handlers in for loop
提问by Philip
I'm having several div's #mydiv1
, #mydiv2
, #mydiv3
, ... and want to assign click handlers to them:
我有几个 div 的#mydiv1
, #mydiv2
, #mydiv3
, ... 并且想为它们分配点击处理程序:
$(document).ready(function(){
for(var i = 0; i < 20; i++) {
$('#question' + i).click( function(){
alert('you clicked ' + i);
});
}
});
But instead of showing 'you clicked 3'
when click on #mydiv3
(as for every other click) I get 'you clicked 20'
. What am I doing wrong?
但是,而不是'you clicked 3'
在单击时显示#mydiv3
(对于其他每次单击),我得到'you clicked 20'
. 我究竟做错了什么?
回答by Harmen
It's a common mistake to create closures in loopsin Javascript. You need to have some sort of callback function like this:
在 Javascript 的循环中创建闭包是一个常见的错误。你需要有这样的回调函数:
function createCallback( i ){
return function(){
alert('you clicked' + i);
}
}
$(document).ready(function(){
for(var i = 0; i < 20; i++) {
$('#question' + i).click( createCallback( i ) );
}
});
Update June 3, 2016:since this question is still getting some traction and ES6 is getting popular as well, I would suggest a modern solution. If you write ES6, you can use the let
keyword, which makes the i
variable local to the loop instead of global:
2016 年 6 月 3 日更新:由于这个问题仍然受到一些关注,而且 ES6 也越来越流行,我建议采用现代解决方案。如果你写 ES6,你可以使用let
关键字,它使i
变量局部于循环而不是全局:
for(let i = 0; i < 20; i++) {
$('#question' + i).click( function(){
alert('you clicked ' + i);
});
}
It's shorter and easier to understand.
它更短,更容易理解。
回答by Donald
To clarify, i is equal to 20 because the click event won't have fired until after the loop has finished.
澄清一下, i 等于 20 因为直到循环完成后才会触发点击事件。
回答by user1490857
$(document).ready(function(){
for(var i = 0; i < 5; i++) {
var $li= $('<li>' + i +'</li>');
(function(i) {
$li.click( function(){
alert('you clicked ' + i);
});
}(i));
$('#ul').append($li);
}
});
回答by Ricardo de Assuncao Goncalves
Using onto attach the 'click' handler you can use the event data in order to pass your data like in:
使用on附加“点击”处理程序,您可以使用事件数据来传递您的数据,例如:
for(var i = 0; i < 20; i++) {
$('#question' + i).on('click', {'idx': i}, function(e) {
alert('you clicked ' + e.data.idx);
});
}
//
// let's creat 20 buttons
//
for(var j = 0; j < 20; j++) {
$('body').append($('<button/>', {type: 'button', id: 'question' + j, text: 'Click Me ' + j}))
}
//
// Passing data to the handler
//
for(var i = 0; i < 20; i++) {
$('#question' + i).on('click', {'idx': i}, function(e) {
console.log('you clicked ' + e.data.idx);
});
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
回答by PleaseStand
You can get by with assigning the click handler once (or at least not making many unnecessary closures). Put all the divs in one class mydivs
, then:
您可以通过分配一次点击处理程序(或至少不进行许多不必要的关闭)。将所有 div 放在一个 class 中mydivs
,然后:
$(document).ready(function(){
$('.mydivs').click(function(){
// Get the number starting from the ID's 6th character
// This assumes that the common prefix is "mydiv"
var i = Number(this.id.slice(5));
alert('you clicked ' + i);
});
});
This looks at the element's ID to get its number, using the slice
string methodto strip the initial letters off.
这会查看元素的 ID 以获取其编号,使用slice
string 方法去除首字母。
Note:It may be better to use
注意:使用可能更好
$('#divcontainer').on('click', '.mydivs', function(){
instead of
代替
$('.mydivs').click(function(){
回答by stancoffyn
Generally, if you are looking to assign click handles to a large number of items, you want to have a container (higher level div) that interprets the clicks for you, as the click bubbles up from the dom.
通常,如果您希望将点击句柄分配给大量项目,您需要一个容器(更高级别的 div)来为您解释点击,因为点击从 dom 冒泡。
<div id="bucket">
<span class="decorator-class" value="3">
...
</div>
<script>
$(document).ready(function(e){
$("#bucket").live('click', function(){
if(e.target).is('span'){
alert("elementid: " + $(e.target).val());
}
}
}
<script>