Можно ли добавить к innerHTML без уничтожения прослушивателей событий потомков?

В следующем примере кода я прикрепляю обработчик события onclick к диапазону, содержащему текст «foo». Обработчик – анонимная функция, которая выдает предупреждение ().

Однако, если я назначаю innerHTML родительского узла, этот обработчик события onclick будет уничтожен – нажатие «foo» не выведет окно предупреждения.

Это исправление?

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

К сожалению, назначение innerHTML вызывает уничтожение всех дочерних элементов, даже если вы пытаетесь добавить. Если вы хотите сохранить дочерние узлы (и их обработчики событий), вам понадобятся функции DOM :

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

Изменить: решение Боба из комментариев. Отправьте свой ответ, Боб! Получите кредит на это. 🙂

 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() сохраняет прослушиватели событий и поддерживается всеми основными браузерами . Это простая однострочная замена для .innerHTML .

 var html_to_insert = "

New paragraph

"; // 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' . Их соответствующие местоположения:

  

Existing content in #mydiv

Теперь это 2012 год, и у jQuery есть функции добавления и добавления, которые делают именно это, добавляют контент, не влияя на текущий контент. Очень полезно.

В качестве небольшой (но связанной) справки, если вы используете javascript-библиотеку, такую ​​как jquery (v1.3) для выполнения манипуляции с dom, вы можете использовать живые события, в которых вы настраиваете обработчик, например:

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

и он будет применяться к этому селектору в любое время при любых манипуляциях с jquery. Для живого события см .: docs.jquery.com/events/live для манипуляции jquery см.: Docs.jquery.com/manipulation

Я создал свою разметку, чтобы вставлять ее в виде строки, поскольку она меньше кода и ее легче читать, чем работать с причудливым домом.

Затем я сделал его innerHTML временного элемента, чтобы я мог взять единственный и единственный дочерний элемент этого элемента и прикрепить его к телу.

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

Потеря обработчиков событий – IMO, ошибка в том, как Javascript обрабатывает 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 } 

Существует еще одна альтернатива: использование setAttribute а не добавление слушателя событий. Как это:

 < !DOCTYPE html>    Demo innerHTML and event listeners    
Click here.

something.innerHTML + = ‘добавить все, что хотите “;

это сработало для меня. Я добавил кнопку для ввода текста, используя это решение.

Вы можете сделать это так:

 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 " + first; lis[j].innerHTML = string; } } 

Я ленивый программист. Я не использую DOM, потому что это похоже на дополнительную типизацию. Для меня, чем меньше код, тем лучше. Вот как я добавил бы «bar» без замены «foo»:

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