是否可以在不破坏后代事件监听器的情况下附加到innerHTML?

mik*_*ike 100 html javascript innerhtml dom-events

在下面的示例代码中,我将onclick事件处理程序附加到包含文本"foo"的span.处理程序是一个匿名函数,弹出alert().

但是,如果我分配给父节点alert(),则此innerHTML事件处理程序将被销毁 - 单击"foo"将无法弹出警告框.

这可以解决吗?

<html>
 <head>
 <script type="text/javascript">

  function start () {
    myspan = document.getElementById("myspan");
    myspan.onclick = function() { alert ("hi"); };

    mydiv = document.getElementById("mydiv");
    mydiv.innerHTML += "bar";
  }

 </script>
 </head>

 <body onload="start()">
   <div id="mydiv" style="border: solid red 2px">
     <span id="myspan">foo</span>
   </div>
 </body>

</html>
Run Code Online (Sandbox Code Playgroud)

Ben*_*ank 116

不幸的是,innerHTML即使你试图追加,分配也会导致所有子元素的破坏.如果要保留子节点(及其事件处理程序),则需要使用DOM函数:

function start() {
    var myspan = document.getElementById("myspan");
    myspan.onclick = function() { alert ("hi"); };

    var mydiv = document.getElementById("mydiv");
    mydiv.appendChild(document.createTextNode("bar"));
}
Run Code Online (Sandbox Code Playgroud)

编辑: Bob的解决方案,来自评论.张贴你的答案,鲍勃!得到它的信任.:-)

function start() {
    var myspan = document.getElementById("myspan");
    myspan.onclick = function() { alert ("hi"); };

    var mydiv = document.getElementById("mydiv");
    var newcontent = document.createElement('div');
    newcontent.innerHTML = "bar";

    while (newcontent.firstChild) {
        mydiv.appendChild(newcontent.firstChild);
    }
}
Run Code Online (Sandbox Code Playgroud)

  • newcontent= document.createElement('div'); newcontent.innerHTML=任意_blob;而 (newcontent.firstChild) mydiv.appendChild(newcontent.firstChild); (58认同)
  • 哦,最后一件事,你需要"var myspan","var newcontent"等,以避免意外溢出全局变量. (2认同)

小智 55

使用.insertAdjacentHTML()保留事件侦听器,并受所有主流浏览器支持.这是一个简单的单线替代品.innerHTML.

var html_to_insert = "<p>New paragraph</p>";

// with .innerHTML, destroys event listeners
document.getElementById('mydiv').innerHTML += html_to_insert;

// with .insertAdjacentHTML, preserves event listeners
document.getElementById('mydiv').insertAdjacentHTML('beforeend', html_to_insert);
Run Code Online (Sandbox Code Playgroud)

'beforeend'参数指定用于在插入HTML内容的元素.选项包括'beforebegin','afterbegin','beforeend',和'afterend'.他们的相应位置是:

<!-- beforebegin -->
<div id="mydiv">
  <!-- afterbegin -->
  <p>Existing content in #mydiv</p>
  <!-- beforeend -->
</div>
<!-- afterend -->
Run Code Online (Sandbox Code Playgroud)

  • @AK_ [规范](//w3c.github.io/DOM-Parsing/#dom-element-insertadjacenthtml) 保证字符串匹配不区分大小写。 (3认同)