委派点击事件仅在第二次点击后才起作用

delegation click event working only after the 2nd click forward

我正在尝试构建和学习原生 javascript event delegation(虽然不确定)像这样

function clicked(d) {
  d.innerText = "clicked";
}
document.addEventListener('click', function() {
  var foos = Array.from(document.getElementsByClassName('foo'));
  foos.forEach(function(elm, i) {
    elm.addEventListener('click', function() {
      clicked(elm);
    });
  });
})

document.body.innerHTML = `<div class="foo"></div><div class="foo"></div><div class="foo"></div><div class="foo"></div>`;
.foo {
  height: 100px;
  width: 100px;
  float: left;
  border: 1px solid green;
}

为什么只有点击 2 次前进后才起作用?

我可以使用 jQuery on 方法更改上面的 addEventListener 代码块以使其正常工作,但我只想知道如何使上面的代码表现得相似。

这是因为您在单击 document 一次之前不会设置 div 上的点击处理程序。

  • 删除 document 上的点击处理程序。
  • 在尝试 select class
  • 之前写信给 dom

function clicked(d) {
  d.innerText = "clicked";
}

document.body.innerHTML = `<div class="foo"></div><div class="foo"></div><div class="foo"></div><div class="foo"></div>`;

var foos = Array.from(document.getElementsByClassName('foo'));
foos.forEach(function(elm, i) {
  elm.addEventListener('click', function() {
    clicked(elm);
  });
});
.foo {
  height: 100px;
  width: 100px;
  float: left;
  border: 1px solid green;
}

事件委托使用事件冒泡和 event.target 属性 来处理多个子元素的事件,其中单个事件处理程序附加到它们的父元素(参见 David Walsh 的 this explanation by Andrew Tetlaw and other examples in this blog post) .

在您的情况下,您不需要为每个 foo div 添加事件处理程序,因为点击事件是在文档级别处理的。您可以简单地检查点击事件的目标是否具有 foo class 并将该目标元素传递给 clicked 函数。

function clicked(d) {
  d.innerText = "clicked";
}

document.addEventListener('click', function(e) {
  if (e.target.className === "foo") {
    clicked(e.target);
  }
});

document.body.innerHTML = '<div class="foo"></div><div class="foo"></div><div class="foo"></div><div class="foo"></div>';
.foo {
  height: 100px;
  width: 100px;
  float: left;
  border: 1px solid green;
}