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

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

Однако, если я назначу родительский узел innerHTML, это onclick Обработчик событий уничтожается - нажатие «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>
77 голосов | спросил mike 27 FebruaryEurope/MoscowbFri, 27 Feb 2009 20:43:14 +0300000000pmFri, 27 Feb 2009 20:43:14 +030009 2009, 20:43:14

11 ответов


0

К сожалению, присваивание 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);
    }
}
ответил Ben Blank 27 FebruaryEurope/MoscowbFri, 27 Feb 2009 20:47:07 +0300000000pmFri, 27 Feb 2009 20:47:07 +030009 2009, 20:47:07
0

Использование .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);

Аргумент 'beforeend' указывает, где в элементе вставлять содержимое HTML. Возможные варианты: 'beforebegin', 'afterbegin', 'beforeend' и 'afterend'. Их соответствующие местоположения:

<!-- beforebegin -->
<div id="mydiv">
  <!-- afterbegin -->
  <p>Existing content in #mydiv</p>
  <!-- beforeend -->
</div>
<!-- afterend -->
ответил Josh de Leeuw 7 WedEurope/Moscow2016-12-07T19:35:10+03:00Europe/Moscow12bEurope/MoscowWed, 07 Dec 2016 19:35:10 +0300 2016, 19:35:10
0

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

ответил rocketsarefast 20 Jpm1000000pmFri, 20 Jan 2012 22:06:15 +040012 2012, 22:06:15
0

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

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

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

ответил Cargowire 28 FebruaryEurope/MoscowbSat, 28 Feb 2009 16:05:32 +0300000000pmSat, 28 Feb 2009 16:05:32 +030009 2009, 16:05:32
0

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

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

var html = '<div>';
html += 'Hello div!';
html += '</div>';

var tempElement = document.createElement('div');
tempElement.innerHTML = html;
document.getElementsByTagName('body')[0].appendChild(tempElement.firstChild);
ответил Eneroth3 4 J000000Wednesday12 2012, 12:08:16
0

Потеря обработчиков событий - это, 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
}
ответил Yes - that Jake. 27 FebruaryEurope/MoscowbFri, 27 Feb 2009 20:48:44 +0300000000pmFri, 27 Feb 2009 20:48:44 +030009 2009, 20:48:44
0

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

 <!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>Demo innerHTML and event listeners</title>
<style>
    div {
        border: 1px solid black;
        padding: 10px;
    }
</style>
</head>
<body>
    <div>
        <span>Click here.</span>
    </div>
    <script>
        document.querySelector('span').setAttribute("onclick","alert('Hi.')");
        document.querySelector('div').innerHTML += ' Added text.';
    </script>
</body>
</html>
ответил Frank Conijn 27 J0000006Europe/Moscow 2018, 06:48:35
0

thing.innerHTML + = 'добавь, что хочешь';

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

ответил KawaiKx 12 J000000Thursday18 2018, 21:45:54
0

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

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;
    }
}
ответил Rishabh gupta 27 MarpmThu, 27 Mar 2014 23:14:25 +04002014-03-27T23:14:25+04:0011 2014, 23:14:25
0

Самый простой способ - использовать массив и помещать в него элементы, а затем динамически вставлять последующие значения в массив. Вот мой код:

var namesArray = [];

function myclick(){
    var readhere = prompt ("Insert value");
    namesArray.push(readhere);
    document.getElementById('demo').innerHTML= namesArray;
}
ответил Anoop Anson 24 +03002018-10-24T11:07:30+03:00312018bEurope/MoscowWed, 24 Oct 2018 11:07:30 +0300 2018, 11:07:30
0

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

function start(){
var innermyspan = document.getElementById("myspan").innerHTML;
document.getElementById("myspan").innerHTML=innermyspan+"bar";
}
ответил lucious 9 J000000Friday10 2010, 18:46:13

Похожие вопросы

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132