Javascript - 在循环中动态分配 onclick 事件
Posted
技术标签:
【中文标题】Javascript - 在循环中动态分配 onclick 事件【英文标题】:Javascript - Dynamically assign onclick event in the loop 【发布时间】:2011-06-29 17:32:40 【问题描述】:我有一个非常简单的带有 js 代码的 html 页面:
<html>
<head>
<title></title>
</head>
<body>
<div id="divButtons">
</div>
<script type="text/javascript">
var arrOptions = new Array();
for (var i = 0; i < 10; i++)
arrOptions[i] = "option" + i;
for (var i = 0; i < arrOptions.length; i++)
var btnShow = document.createElement("input");
btnShow.setAttribute("type", "button");
btnShow.value = "Show Me Option";
var optionPar = arrOptions[i];
btnShow.onclick = function()
showParam(optionPar);
document.getElementById('divButtons').appendChild(btnShow);
function showParam(value)
alert(value);
</script>
</body>
</html>
该页面绑定了 10 个按钮,但是当您单击任何按钮时,它总是显示警报“option9”。如何分配 onclick 事件以显示对应选项!?
谢谢!
【问题讨论】:
【参考方案1】: pp();
function pp()
for(j=0;j<=11;j++)
if(j%4==0)
html+= "<br>";
html += "<span class='remote' onclick='setLift(this)' >"+ j+"</span>";
document.getElementById('el').innerHTML = html;
function setLift(x)
alert(x.innerHTML);
【讨论】:
【参考方案2】:接受的答案是正确的,但我觉得没有做真正的解释。
让我试着解释一下,这里的问题是经典的缺少闭包。
每次循环迭代,变量“i”都会增加 1, 而on-click事件实际上并没有被执行,无论是否只应用于a元素,它都会被汇总到arrOptions的长度为10。
所以,循环一直持续到 'i' 为 10, 然后,每当触发点击事件时,它都会取 i 的值,即 10。
现在,对于解决方案, 在解决方案中,我们使用了闭包,因此当我们将“i”的值应用于 a 元素的点击事件时,它实际上会及时获得 i 的确切值。
onclick 事件的内部函数创建一个闭包,它引用参数 (arrOptions[i]),这意味着实际的 i 变量在正确的时间是什么。
函数最终以该值安全关闭, 然后可以在执行点击事件时返回其对应的值。
【讨论】:
【参考方案3】:接受的答案似乎有效,但似乎令人困惑并且有点麻烦。更好的方法可能是为您要为其分配事件侦听器的元素使用 data 属性。它简单,易于理解,并且代码更少。这是一个例子:
btnShow.data = arrOptions[i];
btnShow.onclick = function()
showParam(this.data);
【讨论】:
【参考方案4】:您只将变量的引用传递给函数,而不是它的值。因此,每次循环迭代时,它都会为您的匿名函数分配一个引用,并且它们都指向内存中的相同值。但是由于您在循环中使用相同的变量名,因此您会覆盖变量的值。您可以将变量连接到字符串以保留其值。比如这样:
btnShow.onclick = new Function("", "showParam(" + arrOptions[i] + ");");
第一个参数是函数的名称,但它是可选的(可以留空或完全省略)。
【讨论】:
【参考方案5】:对于 jquery,请查看API 中的添加事件数据部分:
...
for (var i = 0; i < arrOptions.length; i++)
$('<input id="btn" type="button" value="Show Me Option"><input>').appendTo("#divButtons")
$('#btn').bind("click",
iCount: i,
function(event)
showParam(arrOptions[iCount]);
);
【讨论】:
【参考方案6】:我附加了一个事件处理程序:
window.onload = function()
var folderElement;
tagFolders = document.getElementById("folders");
for (i = 0; i < folders.length; i++)
folderElement = folderButtons[i];
folderElement = document.createElement("button");
folderElement.setAttribute("id", folders[i]);
folderElement.setAttribute("type", "button");
folderElement.innerHTML = folders[i];
if (typeof window.addEventListener !== "undefined")
folderElement.addEventListener("click", getFolderElement, false);
else
folderElement.attachEvent("onclick", getFolderElement);
tagFolders.appendChild(folderElement);
它可以从触发事件的元素中检索任何东西:
// This function is the event handler for the folder buttons.
function getFolderElement(event)
var eventElement = event.currentTarget;
updateFolderContent(eventElement.id);
在这种情况下,您必须将选项嵌入到元素/标签中。在我的情况下,我使用 id。
【讨论】:
【参考方案7】:考虑当 onclick() 函数被执行时,它所拥有的只是:
showParam(optionPar);
,逐字逐句。 optionPar 将在单击事件执行时解析,此时它很可能是您分配给它的最新值。您通常应该避免以这种方式传递变量。
你要解决的问题最好通过重写以下文章来解决:
btnShow.value = "Show Me Option";
var optionPar = arrOptions[i];
btnShow.optionPar = optionPar;
btnShow.onclick = function(e)
// if I'm not mistaking on how to reference the source of the event.
// and if it would work in all the browsers. But that's the idea.
showParam(e.source.optionPar);
【讨论】:
【参考方案8】:你必须这样做:
btnShow.onclick = (function(opt)
return function()
showParam(opt);
;
)(arrOptions[i]);
【讨论】:
这里实际发生了什么?这对我也有用,但我也想理解:-) @MartinElvar 他创建了一个参数是 opt 的函数,然后当我们应用 (...)(arrOptions[i]) 然后它被传递给 opt 然后当我们点击 btnShow 然后这个函数使用已设置的参数调用。 一个更好的方法是使用节点的“data”属性,然后使用this.data作为函数的参数,这不会让人感到困惑。这是一个示例:btnShow.data = arrOptions[i]; btnShow.onclick = function() showParam(this.data);
以上是关于Javascript - 在循环中动态分配 onclick 事件的主要内容,如果未能解决你的问题,请参考以下文章
在 Javascript 的 for 循环中分配点击处理程序