在 for 循环中绑定事件处理程序
Binding eventhandlers in a for-loop
我正在循环中创建 html 个元素,并希望将事件处理程序附加到某些元素。这个处理程序需要知道触发事件的元素的 id,所以我添加了元素 id 作为绑定函数的参数,但是无论如何我最后点击了什么元素,函数总是收到最后一个元素的 id,不是我点击的元素。
这是代码(在下一个代码块中有更简化的版本)(我正在使用 jQuery,但这不是 jQuery 问题,只是 JavaScript-问题)
receiveObjects = function (JSONobj, StatusString, jqXHR) {
var html, i, el;
// error-handling is not shown here
html = '<table>';
for (i = 0; i < JSONobj.list.length; i++) {
el = JSONobj.list[i];
html += '<tr>';
html += '<td class="td1" id="td1'+el.itemID+'">';
html += '<table>';
html += '<tr>';
html += '<td><img id="up9x'+el.itemID+'" src="pics/arrowUp9.png" alt="" style="width:25px;height:66px;"></td>';
html += '<td><img id="up3x'+el.itemID+'" src="pics/arrowUp3.png" alt="" style="width:25px;height:66px;"></td>';
html += '<td><img id="up1x'+el.itemID+'" src="pics/arrowUp1.png" alt="" style="width:25px;height:66px;"></td>';
html += '</tr>';
html += '<tr>';
html += '<td><img id="down9x'+el.itemID+'" src="pics/arrowDown9.png" alt="" style="width:25px;height:66px;"></td>';
html += '<td><img id="down3x'+el.itemID+'" src="pics/arrowDown3.png" alt="" style="width:25px;height:66px;"></td>';
html += '<td><img id="down1x'+el.itemID+'" src="pics/arrowDown1.png" alt="" style="width:25px;height:66px;"></td>';
html += '</tr>';
html += '<tr>';
html += '<td colspan="3">';
html += '<div><button id="delete'+el.itemID+'" name="delete'+el.itemID+'" value="delete'+el.itemID+'">delete</button></div>';
html += '<div id="saveDiv'+el.itemID+'" style="display:none;">';
html += '<button id="save'+el.itemID+'" name="save'+el.itemID+'" value="save'+el.itemID+'">save</button>';
html += '</div>';
html += '</td>';
html += '</tr>';
html += '</table>';
html += '</td>';
html += '<td class="td2" id="td2'+el.itemID+'">';
html += '<table>';
html += '<tr>';
html += '<td>Titel </td>';
html += '<td>';
html += '<input class="grau" type="text" id="inTitel'+el.itemID+'" size="30" maxsize="50" value="'+el.Titel+'">';
html += '</td>';
html += '</tr>';
html += '<tr>';
html += '<td>ET</td>';
html += '<td>';
html += '<input class="grau" type="text" id="inET'+el.itemID+'" size="20" maxsize="30" value="'+el.ET+'">';
html += '</td>';
html += '</tr>';
html += '<tr>';
html += '<td>Text </td>';
html += '<td>';
html += '<textarea class="grau" id="inText'+el.itemID+'" rows="4" cols="30">'+el.Text+'</textarea>';
html += '</td>';
html += '</tr>';
html += '</table>';
html += '<button id="loadPdf'+el.itemID+'" name="loadPdf'+el.itemID+'" value="loadPdf'+el.itemID+'">upload pdf</button>';
html += '</td>';
html += '<td class="td3" id="td3'+el.itemID+'">';
html += '<img src="'+el.pic+'">';
html += '<div>';
html += '<button id="newPic'+el.itemID+'" name="newPic'+el.itemID+'" value="newPic'+el.itemID+'">create pic from pdf</button> ';
html += '</div>';
html += '</td>';
html += '</tr>';
}
html += '</table><div class="ErrorMsg" id="changeRedError"></div>';
$('#workBlock').html(html);
//after the elements are inserted into the dom, the eventhandlers should be binded:
for (i = 0; i < JSONobj.list.length; i++) {
el = JSONobj.list[i];
$('#up9x'+el.itemID).on('click',function(){evHd.clickMove(el.itemID,-9);})
$('#up3x'+el.itemID).on('click',function(){evHd.clickMove(el.itemID,-3);})
$('#up1x'+el.itemID).on('click',function(){evHd.clickMove(el.itemID,-1);})
$('#down9x'+el.itemID).on('click',function(){evHd.clickMove(el.itemID,9);})
$('#down3x'+el.itemID).on('click',function(){evHd.clickMove(el.itemID,3);})
$('#down1x'+el.itemID).on('click',function(){evHd.clickMove(el.itemID,1);})
$('#delete'+el.itemID).on('click',function(){evHd.clickDelete(el.itemID);})
$('#save'+el.itemID).on('click',function(){evHd.clickSave(el.itemID);})
$('#inTitel'+el.itemID).on('change keyup paste mouseup',function(){evHd.changed(el.itemID);})
$('#inET'+el.itemID).on('change keyup paste mouseup',function(){evHd.changed(el.itemID);})
$('#inText'+el.itemID).on('change keyup paste mouseup',function(){evHd.changed(el.itemID);})
$('#loadPdf'+el.itemID).on('click',function(){evHd.clickLoadPdf(el.itemID);})
$('#newPic'+el.itemID).on('click',function(){evHd.clickNewPic(el.itemID);})
}
}
问题一定出在我将 id (el.itemID
) 附加到事件处理函数的方式上。简体:
for (i = 0; i < 500; i++) {
el = JSONobj.list[i];
$('#prefix'+i).on('click',function(){
handler(i); //this seems to be problematic
})
}
我想我知道问题出在哪里,但我不知道如何解决。你能帮忙吗?
这是一个非常常见的错误,由于 JavaScript 的 闭包 概念(函数加上指向函数外部的所有变量的指针,这些变量已在函数体)。您可以使用 IIFE(立即调用的函数表达式)解决此问题:
for (i = 0; i < 500; i++) {
(function(num) {
$('#prefix' + num).on('click',function() {
handler(num);
})
})(i);
}
这个立即调用的函数将创建一个新范围,因此将正确的 i
保存在 num
中。否则,JavaScript 的闭包(该函数在 i
上保留一个指针,因此在 for
循环结束后始终引用 500)会扰乱您的事件处理程序。
我正在循环中创建 html 个元素,并希望将事件处理程序附加到某些元素。这个处理程序需要知道触发事件的元素的 id,所以我添加了元素 id 作为绑定函数的参数,但是无论如何我最后点击了什么元素,函数总是收到最后一个元素的 id,不是我点击的元素。
这是代码(在下一个代码块中有更简化的版本)(我正在使用 jQuery,但这不是 jQuery 问题,只是 JavaScript-问题)
receiveObjects = function (JSONobj, StatusString, jqXHR) {
var html, i, el;
// error-handling is not shown here
html = '<table>';
for (i = 0; i < JSONobj.list.length; i++) {
el = JSONobj.list[i];
html += '<tr>';
html += '<td class="td1" id="td1'+el.itemID+'">';
html += '<table>';
html += '<tr>';
html += '<td><img id="up9x'+el.itemID+'" src="pics/arrowUp9.png" alt="" style="width:25px;height:66px;"></td>';
html += '<td><img id="up3x'+el.itemID+'" src="pics/arrowUp3.png" alt="" style="width:25px;height:66px;"></td>';
html += '<td><img id="up1x'+el.itemID+'" src="pics/arrowUp1.png" alt="" style="width:25px;height:66px;"></td>';
html += '</tr>';
html += '<tr>';
html += '<td><img id="down9x'+el.itemID+'" src="pics/arrowDown9.png" alt="" style="width:25px;height:66px;"></td>';
html += '<td><img id="down3x'+el.itemID+'" src="pics/arrowDown3.png" alt="" style="width:25px;height:66px;"></td>';
html += '<td><img id="down1x'+el.itemID+'" src="pics/arrowDown1.png" alt="" style="width:25px;height:66px;"></td>';
html += '</tr>';
html += '<tr>';
html += '<td colspan="3">';
html += '<div><button id="delete'+el.itemID+'" name="delete'+el.itemID+'" value="delete'+el.itemID+'">delete</button></div>';
html += '<div id="saveDiv'+el.itemID+'" style="display:none;">';
html += '<button id="save'+el.itemID+'" name="save'+el.itemID+'" value="save'+el.itemID+'">save</button>';
html += '</div>';
html += '</td>';
html += '</tr>';
html += '</table>';
html += '</td>';
html += '<td class="td2" id="td2'+el.itemID+'">';
html += '<table>';
html += '<tr>';
html += '<td>Titel </td>';
html += '<td>';
html += '<input class="grau" type="text" id="inTitel'+el.itemID+'" size="30" maxsize="50" value="'+el.Titel+'">';
html += '</td>';
html += '</tr>';
html += '<tr>';
html += '<td>ET</td>';
html += '<td>';
html += '<input class="grau" type="text" id="inET'+el.itemID+'" size="20" maxsize="30" value="'+el.ET+'">';
html += '</td>';
html += '</tr>';
html += '<tr>';
html += '<td>Text </td>';
html += '<td>';
html += '<textarea class="grau" id="inText'+el.itemID+'" rows="4" cols="30">'+el.Text+'</textarea>';
html += '</td>';
html += '</tr>';
html += '</table>';
html += '<button id="loadPdf'+el.itemID+'" name="loadPdf'+el.itemID+'" value="loadPdf'+el.itemID+'">upload pdf</button>';
html += '</td>';
html += '<td class="td3" id="td3'+el.itemID+'">';
html += '<img src="'+el.pic+'">';
html += '<div>';
html += '<button id="newPic'+el.itemID+'" name="newPic'+el.itemID+'" value="newPic'+el.itemID+'">create pic from pdf</button> ';
html += '</div>';
html += '</td>';
html += '</tr>';
}
html += '</table><div class="ErrorMsg" id="changeRedError"></div>';
$('#workBlock').html(html);
//after the elements are inserted into the dom, the eventhandlers should be binded:
for (i = 0; i < JSONobj.list.length; i++) {
el = JSONobj.list[i];
$('#up9x'+el.itemID).on('click',function(){evHd.clickMove(el.itemID,-9);})
$('#up3x'+el.itemID).on('click',function(){evHd.clickMove(el.itemID,-3);})
$('#up1x'+el.itemID).on('click',function(){evHd.clickMove(el.itemID,-1);})
$('#down9x'+el.itemID).on('click',function(){evHd.clickMove(el.itemID,9);})
$('#down3x'+el.itemID).on('click',function(){evHd.clickMove(el.itemID,3);})
$('#down1x'+el.itemID).on('click',function(){evHd.clickMove(el.itemID,1);})
$('#delete'+el.itemID).on('click',function(){evHd.clickDelete(el.itemID);})
$('#save'+el.itemID).on('click',function(){evHd.clickSave(el.itemID);})
$('#inTitel'+el.itemID).on('change keyup paste mouseup',function(){evHd.changed(el.itemID);})
$('#inET'+el.itemID).on('change keyup paste mouseup',function(){evHd.changed(el.itemID);})
$('#inText'+el.itemID).on('change keyup paste mouseup',function(){evHd.changed(el.itemID);})
$('#loadPdf'+el.itemID).on('click',function(){evHd.clickLoadPdf(el.itemID);})
$('#newPic'+el.itemID).on('click',function(){evHd.clickNewPic(el.itemID);})
}
}
问题一定出在我将 id (el.itemID
) 附加到事件处理函数的方式上。简体:
for (i = 0; i < 500; i++) {
el = JSONobj.list[i];
$('#prefix'+i).on('click',function(){
handler(i); //this seems to be problematic
})
}
我想我知道问题出在哪里,但我不知道如何解决。你能帮忙吗?
这是一个非常常见的错误,由于 JavaScript 的 闭包 概念(函数加上指向函数外部的所有变量的指针,这些变量已在函数体)。您可以使用 IIFE(立即调用的函数表达式)解决此问题:
for (i = 0; i < 500; i++) {
(function(num) {
$('#prefix' + num).on('click',function() {
handler(num);
})
})(i);
}
这个立即调用的函数将创建一个新范围,因此将正确的 i
保存在 num
中。否则,JavaScript 的闭包(该函数在 i
上保留一个指针,因此在 for
循环结束后始终引用 500)会扰乱您的事件处理程序。