将 eventListener 添加到具有相同 class 名称但不同 id 的 div 会覆盖之前的 eventListener

Adding eventListener to divs with same class name but different id overrides previous eventListener

我在 javascript 文件的 for 循环中创建了一堆 div。它们具有相同的 class 名称但不同的 ID。

我通过 for 循环添加了一个事件侦听器,但我以前的分配被覆盖了,现在所有的 div 都有完全相同的事件侦听器。当我点击它们时,它们都做同样的事情。

这是我的代码:

JS:

for (var i = 1; i <= arraySize; ++i) {
    var childdiv = document.createElement('div');
    childdiv.className = 'small';
    childdiv.id = 'id' + i;
//...
}
 //....
for (var i = 0; i < arraySize; i++) {
    var smalldiv = document.getElementById('id' + (i + 1));

    var execCommand = parseFile(filesArray[i], "Exec");
    console.log(execCommand);
    smalldiv.addEventListener('click', function(event) {
        exec(execCommand, function(error, stdout, stderr) {})
    })

}

我认为这应该可行,因为我指定了不同的 ID,但我不确定。

如有任何帮助,我们将不胜感激!

试试这个方法

for (var i = 1; i <= arraySize; ++i) {
    var childdiv = document.createElement('div');
    childdiv.className = 'small';
    childdiv.id = 'id' + i;
    //...
    //....

    var execCommand = parseFile(filesArray[i], "Exec");
    console.log(execCommand);
    childdiv.addEventListener('click', function(event) {
        exec(execCommand, function(error, stdout, stderr) {})
    })

    //TOOD: append element to DOM
    // document.body.append(childdiv);
}

创建元素后,在添加到 DOM 之前必须完全描述以防止出现一些错误

问题是用 var 关键字声明的变量不是 block-scoped。这意味着尽管在每次循环迭代中您都声明 var execCommand 它们在整个函数/全局上下文中都被视为一个变量。因此,作为 click 事件侦听器传递的所有函数都看到相同的 execCommand 变量。此变量的值等于在最终循环迭代中分配的值。这就是为什么当您单击 div 时您会看到相同结果的原因。

解决方法很简单。将 execCommand 变量声明为 block-scoped。可以使用 letconst 关键字来完成。

for (var i = 0; i < arraySize; i++) {
    var smalldiv = document.getElementById('id' + (i + 1));

    const execCommand = parseFile(filesArray[i], "Exec");
    console.log(execCommand);
    smalldiv.addEventListener('click', function(event) {
        exec(execCommand, function(error, stdout, stderr) {})
    })

}

如果由于某种原因您不能在代码中使用 letconst,仍然有可能获得相同的总体结果。您将一段代码放入附加函数中,并使用 var 声明的变量作为参数调用此函数。然后这个变量是 function-scoped 所以代码按预期工作。

for (var i = 0; i < arraySize; i++) {
    var smalldiv = document.getElementById('id' + (i + 1));

    var execCommand = parseFile(filesArray[i], "Exec");
    console.log(execCommand);

    (function(execParam) {
        smalldiv.addEventListener('click', function(event) {
            exec(execParam, function(error, stdout, stderr) {})
        });
    })(execCommand);

}

您可以通过在 for 循环中使用 let i = 0 来解决这个问题,或者您可以像下面这样包装一个 IIFE(如果不使用 ES6)

const els = document.querySelectorAll('button')
for (var i = 0; i < els.length; i++) {
  (function(j) {
    els[i].addEventListener('click', function(e) {
      console.log(j);
    });
  })(i)
}
<button id="btn0">Button 0</button>
<button id="btn1">Button 1</button>
<button id="btn2">Button 2</button>
<button id="btn3">Button 3</button>