使用带有args的onclick处理程序进行克隆

时间:2016-06-03 23:39:40

标签: javascript jquery html5 clone

我正在克隆一个元素,该元素将有一个onclick处理程序。该事件处理程序将作为参数发送ID。 我的问题是当我点击元素时,他会发送cicle的最后一个ID。

这是我的javascript代码:

function cloneActions(idRoutine){ //clone elements 
    var actionDiv = document.getElementById("actionsImages-"+idRoutine).getElementsByClassName("actionImage"); //parent with content that must be cloned
    var allActions = document.getElementById("actions"); //parent div
    while (allActions.firstChild) { //remove all existing imgs
         allActions.removeChild(allActions.firstChild);
    }
    for(var i=0; i < actionDiv.length; i++){ //set all images and handlers
       var image = actionDiv[i].cloneNode(true);
       var id = image.id;
       image.onclick = function() { selectAction(id);};
       allActions.appendChild(image);
    }       
}
function selectAction(id){ //handler function
    ///jquery
}

和html代码:

<div id="actionsImages-«id»" class="tile__list actionsImages">
    <img src='sortable/st/foo.jpg' class='actionImage' id=«id» title='foo'/>
</div>

我做错了什么?

1 个答案:

答案 0 :(得分:1)

这是您在javascript中for循环,变量提升和异步事件的教训。别担心,我们都经历过这一课。这是:

这是你的for循环:

for(var i=0; i < actionDiv.length; i++) {
   var image = actionDiv[i].cloneNode(true);
   var id = image.id;
   image.onclick = function() { selectAction(id);};
   allActions.appendChild(image);
}

这与执行此操作相同:

var image;
var id;
for(var i=0; i < actionDiv.length; i++) {
   image = actionDiv[i].cloneNode(true);
   id = image.id;
   image.onclick = function() { selectAction(id);};
   allActions.appendChild(image);
}

这是因为variables in javascript are hoisted to the the top of their scope在运行时。这意味着您的for循环运行,您的变量imageid在循环的每次迭代中都设置为新值,并且当循环完成时,变量是保持循环最后一次迭代的

(再次以粗体显示最后一部分)

然后,在将来的某个时间,您的用户点击图片,您的点击处理程序调用函数selectAction并传递id。好吧,如果您再次以粗体读取该文本,那么您的id变量将保留for循环的最后一次迭代中的

(再次以粗体显示最后一部分)

为了说明问题,我们将它剥离到裸骨。将此代码复制到您的控制台:

for (var i = 0; i < 5; i++) {
    var someVar = i;
    setTimeout(function () {
        console.log("The value of 'someVar' is " + someVar);
    }, i * 300);
}

每次查看someVar如何等于4。这是你问题的症结所在。

要解决您的问题,您可以使用“绑定”功能,如下所示:

var image, id, i;
for(i=0; i < actionDiv.length; i++) {
   image = actionDiv[i].cloneNode(true);
   id = image.id;
   image.onclick = selectAction.bind(image, id)
   allActions.appendChild(image);
}

我将让您了解函数绑定的工作原理here

另一个解决方案是让你在for循环中调用一个函数:

function doCoolStuff (i) {
   var image = actionDiv[i].cloneNode(true);
   var id = image.id;
   image.onclick = function () { selectAction(id); };
   allActions.appendChild(image);
}

for(var i=0; i < actionDiv.length; i++) {
   doCoolStuff(i);
}