Javascript - 在循环中动态分配onclick事件

时间:2011-02-18 10:19:07

标签: javascript html events button onclick

我的jtml代码非常简单的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事件来显示相应的选项!?

谢谢!

7 个答案:

答案 0 :(得分:29)

你必须做这样的事情:

btnShow.onclick = (function(opt) {
    return function() {
       showParam(opt);
    };
})(arrOptions[i]);

答案 1 :(得分:2)

考虑到当执行onclick()函数时,它所拥有的只有:

showParam(optionPar);

,逐字。 optionPar将在执行click事件时解析,此时它很可能是您为其分配的最新值。通常应该避免以这种方式传递变量。

您尝试解决的问题最好通过重写以下内容来解决:

            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);
            }

答案 2 :(得分:1)

我附上了一个事件处理程序:

        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);
}

在这种情况下,您必须在element / tag中嵌入选项。在我的情况下,我使用id。

答案 3 :(得分:1)

对于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]);
    });
}

答案 4 :(得分:1)

接受的答案似乎有效,但似乎令人困惑,并且有点麻烦。一种更好的方法可能是使用数据属性来查找要为其分配事件侦听器的元素。它简单易懂,代码少。这是一个例子:

btnShow.data = arrOptions[i];

btnShow.onclick = function() {
  showParam(this.data);
}

答案 5 :(得分:1)

接受的答案是正确的,但我觉得没有做出真正的解释。

让我试着解释一下,这里的问题是经典的缺失闭包。

变量&#39; i&#39;每循环迭代增加1, 并且实际上没有执行点击事件,无论是否仅应用于a元素,它总结为arrOptions的长度为10。

所以,循环继续,直到&#39; i&#39;是10, 然后,每当触发on-click事件时,它取i的值为10.

现在,对于解决方案, 在解决方案中我们使用了一个闭包,这样当我们应用&#39; i&#39;对于a元素的on-click事件,它实际上获得了i的准确值。

onclick事件的内部函数创建一个闭包,它引用参数(arrOptions [i]),这意味着实际的i变量在正确的时间。

该函数最终安全地以该值关闭, 然后可以在执行点击事件时返回其相应的值。

答案 6 :(得分:0)

您只将变量的引用传递给函数,而不是它的值。因此,每次循环迭代时,它都会为您的匿名函数分配一个引用,并且它们都指向内存中的相同值。但由于您在循环中使用相同的变量名称,因此会覆盖变量的值。您可以将变量连接到字符串以保留其值。例如:

btnShow.onclick = new Function("", "showParam(" + arrOptions[i] + ");");

第一个参数是函数的名称,但是afaik是可选的(它可以留空或完全省略)。