通过 HTML 字符串添加的元素会禁用先前元素的 onclicks/事件侦听器

问题描述 投票:0回答:1

通过 HTML 字符串添加的元素会禁用先前元素的 onclicks/事件侦听器

小提琴:https://jsfiddle.net/eptcrwfd/37/

解决方案是将 onclick 声明放在 setTimeout 中,时间最短

setTimeout(() => {
  document.getElementById("element-id").onclick = () => {
  console.log(1)
  }
})

但这似乎不是最好的方法,我仍然想知道是什么导致了这种行为

javascript html dom
1个回答
0
投票

表达

document.body.innerHTML += ...
并不像你想象的那么优雅或高效。它实际上是

的简写符号
  • 以 HTML 字符串的形式获取迄今为止现有的 DOM 内容(没有任何可能已经定义的事件侦听器!)
  • 将字符串添加到
    +=
    运算符后面并且
  • 再次解析结果字符串

这不仅非常慢,而且还会删除所有先前分配的事件侦听器。

向现有元素添加新的 HTML 代码块的更安全、更有效的方法是

document.body.insertAdjacentHTML("beforeend","... new HTML code")
。这将使之前构建的 DOM 保持完整,包括所有事件侦听器。

function addButtons(){
  const a = document.createElement("button")
  a.innerHTML = "button1"
  a.className = "button"
  a.id = "button-1"
  document.body.appendChild(a)
  //works only when done this way
  setTimeout(()=>{
  document.getElementById("button-1").onclick = ()=>
  {console.log(1)}
  })
  
  document.body.insertAdjacentHTML("beforeend",
  "<button id='button2' class='button'>button2</button>")
  
  document.getElementById("button2").onclick = ()=>{console.log(2)}
}
function addButtons1(){
const a = document.createElement("button")
  a.innerHTML = "button3"
  a.className = "button"
  //works when button4 is absent
  a.addEventListener("click", ()=>{console.log(3)})
  document.body.appendChild(a)
  
  document.body.insertAdjacentHTML("beforeend",
  "<button id='button4' class='button'>button4</button>")
  //works
  document.getElementById("button4").onclick = ()=>{console.log(4)}
}
function addButtons2(){
const a = document.createElement("button")
  a.innerHTML = "button5"
  a.className = "button"
  //works
  a.onclick = ()=>{console.log(5)}
  document.body.appendChild(a)
  
  
const b = document.createElement("button")
  b.innerHTML = "button6"
  b.className = "button"
  //works
  b.onclick = ()=>{console.log(6)}
  document.body.appendChild(b)
}

addButtons()
addButtons1()
addButtons2()

© www.soinside.com 2019 - 2024. All rights reserved.