Javascript - 在循环中动态分配 onclick 事件
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/5040069/
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
Javascript - Dynamically assign onclick event in the loop
提问by ihorko
I have very simple html page with js code:
我有一个非常简单的带有 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>
That page binds 10 buttons, but when you click on any button it always shows alert "option9". How is it possible assign onclick event to show correspondent option !?
该页面绑定了 10 个按钮,但是当您单击任何按钮时,它始终显示警报“option9”。怎么可能分配 onclick 事件来显示相应的选项!?
Thanks!
谢谢!
回答by Jacob Relkin
You'll have to do something like this:
你必须做这样的事情:
btnShow.onclick = (function(opt) {
return function() {
showParam(opt);
};
})(arrOptions[i]);
回答by Pawel Veselov
Consider the fact that when the onclick() function is executed, all it has is:
考虑这样一个事实,当 onclick() 函数被执行时,它只有:
showParam(optionPar);
, verbatim. The optionPar will be resolve at the time the click event is executed, and at this point it most likely be the latest value you assigned to it. You should generally avoid passing variables in such a way.
,逐字逐句。optionPar 将在执行单击事件时解析,此时它很可能是您分配给它的最新值。您通常应该避免以这种方式传递变量。
The problem you are trying to solve is best solved by re-writing the piece such as:
您试图解决的问题最好通过重写以下内容来解决:
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);
}
回答by Günter
I attach an event handler:
我附上一个事件处理程序:
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);
}
which can retrieve anything from the element that triggered the event:
它可以从触发事件的元素中检索任何内容:
// This function is the event handler for the folder buttons.
function getFolderElement(event) {
var eventElement = event.currentTarget;
updateFolderContent(eventElement.id);
}
in which case you have to embed the option inside the element / tag. In my case I use the id.
在这种情况下,您必须将选项嵌入到元素/标签中。在我的情况下,我使用 id。
回答by Roman
For jquery, check out the adding event datasection from the API:
对于 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]);
});
}
回答by ray_voelker
The accepted answer seems to work, but seems to be confusing and a somewhat cumbersome way to do it. A better way perhaps might be to use the data attribute for the element you're looking to assign the event listener for. It's simple, easy to understand, and way less code. Here's an example:
接受的答案似乎有效,但似乎令人困惑并且是一种有点麻烦的方法。更好的方法可能是对要为其分配事件侦听器的元素使用 data 属性。它很简单,易于理解,而且代码更少。下面是一个例子:
btnShow.data = arrOptions[i];
btnShow.onclick = function() {
showParam(this.data);
}
回答by john Smith
The accepted answer is correct but I feel that no real explanation was done.
接受的答案是正确的,但我觉得没有做真正的解释。
Let me try to explain, the issue here is classical missing closure.
让我试着解释一下,这里的问题是经典的缺失闭包。
The variable 'i' is getting increased by 1 per loop iteration, and the on-click event actually is not being executed, whether only applied to the a element, it getting summarize up to the length of arrOptions which is 10.
变量 'i' 每次循环迭代增加 1,并且实际上没有执行点击事件,无论是否仅应用于 a 元素,它都会汇总到 arrOptions 的长度,即 10。
So, the loop continues up until 'i' is 10, Then, whenever the on-click event is being triggered, it takes the value of i which is 10.
因此,循环一直持续到 'i' 为 10,然后,每当触发点击事件时,它都会取 i 的值,即 10。
now, for the solution, in the solution we are using a closure, so that when we apply the value of 'i' to the on-click event of the a element, it actually gets the exact value of i at in time.
现在,对于解决方案,在解决方案中我们使用了一个闭包,这样当我们将 'i' 的值应用于 a 元素的点击事件时,它实际上会及时获得 i 的确切值。
The inner function of the onclick event create a closure where it references the parameter (arrOptions[i]), meaning what the actual i variable is at the right time.
onclick 事件的内部函数创建一个闭包,它引用参数 (arrOptions[i]),这意味着在正确的时间实际 i 变量是什么。
The function eventually closes with that value safely, and can then return its corresponding value when the on-click event is being executed.
该函数最终以该值安全地关闭,然后可以在执行点击事件时返回其相应的值。
回答by StanE
You pass just the reference of the variable to the function, not it's value. So every time the loop is iterated, it assigns a reference to your anonymous function and all of them point to the same value in memory. But since you use the same variable name in the loop, you overwrite the value of the variable. You can concatenate the variable to a string to preserve it's value. For example like that:
您只将变量的引用传递给函数,而不是它的值。因此,每次循环迭代时,它都会为您的匿名函数分配一个引用,并且所有这些引用都指向内存中的相同值。但是由于您在循环中使用了相同的变量名,因此您覆盖了变量的值。您可以将变量连接到字符串以保留其值。例如像这样:
btnShow.onclick = new Function("", "showParam(" + arrOptions[i] + ");");
The first parameter is the name of the function but afaik it is optional (it can be left blank or omitted at all).
第一个参数是函数的名称,但它是可选的(可以留空或完全省略)。