在 DOM(在 javascript 中)中显示后,无法在 createElement()(按钮)上使用 addEventListener()

Cannot use addEventListener() on a createElement() (a button) after displaying it in the DOM (in javascript)

我最近在创建一个Javascript框架,我面临两个我完全不明白的问题。当我在 Javascript 中创建一个带有 createElement() 的新按钮时,我不能同时将它放在几个元素中而不终止“点击”事件(如果这是一个 id,它有效)。

(注:"button.onclick = function()"也不行)

这是代码:(我不想使用任何库)

function createButton() {
    var button = document.createElement("button");
    button.innerHTML = "YOOOO";
    button.style.backgroundColor = "red";
    button.style.color = "white";

    // Problem Two : If I click on the button, nothing happends
    button.addEventListener("click", function(e) {
        alert(e.target);
    }, false);

    var clas = document.getElementsByClassName("test");
    Array.from(clas).forEach(element => {
        element.appendChild(button);
        element.innerHTML += ""; // First problem : If I don't do this, the button does not appear in the first div. I have no idea why !
    });
}
createButton();
 body {
    margin: 0;
    padding: 0;
    display:flex;
    justify-content: center;
    align-items: center;
    height: 100vh;
    background-color: rgba(30, 30, 30, 0.2);
}

button {
    cursor: pointer;
    width: 80px;
    height: 50px;
    padding: 10px;
}
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>bug</title>
</head>

<body>

<div class="test" id="1" style="padding: 50px;">
    <span>1</span>
</div>
<div class="test" id="2" style="padding: 50px;">
    <span>2</span>
</div>

</body>
</html>

有2个问题:

  • element.innerHTML += "";,其中 element 指的是按钮的 父级 ,将强制父级 re-parse 其内容从他们的 HTML 字符串,从而破坏子元素上的任何现有处理程序。侦听器附加到的元素将从 DOM 中删除并替换为不同的元素;新的没有监听器

  • 当您执行 appendChild 时,如果要追加的元素已经存在于 DOM 中,它将在追加到新元素之前从它之前存在的位置移除地点。由于您只执行 document.createElement('button') 一次,没有 innerHTML += '',当按钮附加到第二个时,按钮将从其第一个位置移除。

改为在循环内创建按钮,两个问题都解决了。

function createButton() {
  var clas = document.getElementsByClassName("test");
  Array.from(clas).forEach(element => {

    var button = document.createElement("button");
    button.innerHTML = "YOOOO";
    button.style.backgroundColor = "red";
    button.style.color = "white";

    // Problem Two : If I click on the button, nothing happends
    button.addEventListener("click", function(e) {
      alert(e.target);
    }, false);
    element.appendChild(button);

  });
}
createButton();
body {
  margin: 0;
  padding: 0;
  display: flex;
  justify-content: center;
  align-items: center;
  height: 100vh;
  background-color: rgba(30, 30, 30, 0.2);
}

button {
  cursor: pointer;
  width: 80px;
  height: 50px;
  padding: 10px;
}
<div class="test" id="1" style="padding: 50px;">
  <span>1</span>
</div>
<div class="test" id="2" style="padding: 50px;">
  <span>2</span>
</div>

或者,让代码更漂亮一点:

function createButton() {
  for (const parent of document.querySelectorAll('.test')) {
    const button = parent.appendChild(document.createElement("button"));
    button.textContent = "YOOOO";
    button.style.backgroundColor = "red";
    button.style.color = "white";
    button.addEventListener("click", function(e) {
      console.log(e.target);
    });
  }
}
createButton();
body {
  margin: 0;
  padding: 0;
  display: flex;
  justify-content: center;
  align-items: center;
  height: 100vh;
  background-color: rgba(30, 30, 30, 0.2);
}

button {
  cursor: pointer;
  width: 80px;
  height: 50px;
  padding: 10px;
}
<div class="test" id="1" style="padding: 50px;">
  <span>1</span>
</div>
<div class="test" id="2" style="padding: 50px;">
  <span>2</span>
</div>

你的按钮是单实例,重复调用

element.appendChild(button);

只需在DOM中重复移动它。

您随后致电

element.innerHTML += "";

从 DOM 中删除该引用,而是从其 outerHTML 中创建一个新的 button。这也是您添加的事件侦听器丢失的地方。

如果您需要多个按钮,您还需要创建多个 按钮。

我强烈建议你委托和克隆

我想我几天前已经为您发布了这个答案

function createButton() {
  const button = document.createElement("button");
  button.classList.add("redwhite");
  button.innerHTML = "YOOOO";
  [...document.querySelectorAll(".test")].forEach(element => {
    element.appendChild(button.cloneNode(true));
  });
}
createButton();
document.getElementById("container").addEventListener("click", function(e) {
  const tgt = e.target;
  if (tgt.classList.contains("redwhite")) {
    console.log(tgt.closest("div").id)
  }  
})
body {
  margin: 0;
  padding: 0;
  display: flex;
  justify-content: center;
  align-items: center;
  height: 100vh;
  background-color: rgba(30, 30, 30, 0.2);
}

button {
  cursor: pointer;
  width: 80px;
  height: 50px;
  padding: 10px;
}

.redwhite {
  background-color: red;
  color: white;
}
<div id="container">
  <div class="test" id="1" style="padding: 50px;">
    <span>1</span>
  </div>
  <div class="test" id="2" style="padding: 50px;">
    <span>2</span>
  </div>
</div>