是否有可能附加到innerHTML而不破坏后代的事件侦听器?

在下面的示例代码中,我将一个onclick事件处理程序附加到包含文本“foo”的跨度。 处理程序是一个匿名函数,popupalert()。

但是,如果我分配给父节点的innerHTML ,这个onclick事件处理程序被破坏 – 单击“foo”将无法popup警告框。

这是可以修复的吗?

 <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> 

不幸的是,赋值给innerHTML会导致所有子元素的破坏,即使你试图追加。 如果您想保留子节点(及其事件处理程序),则需要使用DOMfunction :

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

编辑:鲍勃的解决scheme,从评论。 发表你的答案,鲍勃! 获得信贷。 🙂

 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); } } 

使用.insertAdjacentHTML()保留事件监听器,并受所有主stream浏览器的支持 。 这是.innerHTML的一个简单的单行replace。

 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); 

'beforeend'参数指定插入HTML内容的元素的位置。 选项是'beforebegin''afterbegin''beforeend''afterend' 。 他们相应的位置是:

 <!-- beforebegin --> <div id="mydiv"> <!-- afterbegin --> <p>Existing content in #mydiv</p> <!-- beforeend --> </div> <!-- afterend --> 

现在是2012年了,jQuery有追加和前置function,可以做到这一点,添加内容而不影响当前的内容。 很有用。

作为一个轻微的(但相关的)的帮助,如果你使用jQuery(v1.3)这样的javascript库来做你的dom操作,你可以利用实时事件来设置一个处理程序,如:

  $("#myspan").live("click", function(){ alert('hi'); }); 

并且在任何types的jQuery操作过程中都会被应用到该select器。 有关直播活动,请参阅: docs.jquery.com/events/live for jquery manipulation请参阅: docs.jquery.com/manipulation

我创build了我的标记插入作为一个string,因为它比较less的代码,更容易阅读比花哨的东西。

然后,我把它作为临时元素的内在,以便我可以把这个元素的独一无二的孩子带到身体上。

 var html = '<div>'; html += 'Hello div!'; html += '</div>'; var tempElement = document.createElement('div'); tempElement.innerHTML = html; document.getElementsByTagName('body')[0].appendChild(tempElement.firstChild); 

失去事件处理程序是,IMO,在处理DOM的方式错误。 为了避免这种行为,可以添加以下内容:

 function start () { myspan = document.getElementById("myspan"); myspan.onclick = function() { alert ("hi"); }; mydiv = document.getElementById("mydiv"); clickHandler = mydiv.onclick; // add mydiv.innerHTML += "bar"; mydiv.onclick = clickHandler; // add } 

你可以这样做:

 var anchors = document.getElementsByTagName('a'); var index_a = 0; var uls = document.getElementsByTagName('UL'); window.onload=function() {alert(anchors.length);}; for(var i=0 ; i<uls.length; i++) { lis = uls[i].getElementsByTagName('LI'); for(var j=0 ;j<lis.length;j++) { var first = lis[j].innerHTML; string = "<img src=\"http://g.etfv.co/" + anchors[index_a++] + "\" width=\"32\" height=\"32\" /> " + first; lis[j].innerHTML = string; } } 

我是一个懒惰的程序员。 我不使用DOM,因为它看起来像额外的打字。 对我来说,代码越less越好。 这里是我将如何添加“酒吧”而不更换“富”:

 function start(){ var innermyspan = document.getElementById("myspan").innerHTML; document.getElementById("myspan").innerHTML=innermyspan+"bar"; }