¿Es posible agregar a internalHTML sin destruir los detectores de eventos de los descendientes?

Resuelto mike asked hace 15 años • 13 respuestas

En el siguiente código de ejemplo, adjunto un onclickcontrolador de eventos al intervalo que contiene el texto "foo". El controlador es una función anónima que muestra un archivo alert().

Sin embargo, si lo asigno al nodo principal innerHTML, este onclickcontrolador de eventos se destruye; al hacer clic en "foo" no aparece el cuadro de alerta.

¿Se puede arreglar esto?

<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>
mike avatar Feb 28 '09 00:02 mike
Aceptado

El uso .insertAdjacentHTML()conserva los detectores de eventos y es compatible con los principales navegadores . Es un reemplazo simple de una línea para .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);

El 'beforeend'argumento especifica en qué parte del elemento se insertará el contenido HTML. Las opciones son 'beforebegin', 'afterbegin', 'beforeend'y 'afterend'. Sus ubicaciones correspondientes son:

<!-- beforebegin -->
<div id="mydiv">
  <!-- afterbegin -->
  <p>Existing content in #mydiv</p>
  <!-- beforeend -->
</div>
<!-- afterend -->
Josh avatar Dec 07 '2016 16:12 Josh

Desafortunadamente, la asignación a innerHTMLcausa la destrucción de todos los elementos secundarios, incluso si intenta agregarlos. Si desea conservar los nodos secundarios (y sus controladores de eventos), necesitará utilizar funciones DOM :

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

    var mydiv = document.getElementById("mydiv");
    mydiv.appendChild(document.createTextNode("bar"));
}

Editar: la solución de Bob, de los comentarios. ¡Publica tu respuesta, Bob! Obtenga crédito por ello. :-)

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);
    }
}
Ben Blank avatar Feb 27 '2009 17:02 Ben Blank