Неожиданное значение «this» в addEventListener

#javascript #events

#javascript #Мероприятия

Вопрос:

Ссылка this на обратный вызов, прикрепленный в качестве прослушивателя к различным элементам, неожиданно изменяется.

Щелчок по одному из трех внутренних разделов правильно указывает на них, но когда контейнер щелкается в первый раз, ссылка на него застревает.
Я что-то упустил?

 function callback(e) {
    this.innerHTML  = '<br/>'   e.type   ' on '   e.target.nodeName   '#'   e.target.id;
    console.log(this);
    e.stopPropagation();
}

document.querySelectorAll('div').forEach(function(div, i) {
    div.addEventListener('click', callback, false);
});  
 #container { border: 1px solid #ddd; padding: 10px; background: #fcfcfc; }
#container div { width: 200px; min-height: 50px; border: 1px solid #ccf; margin:5px; padding: 10px; background: #eef; }  
 <div id="container">
  I am the container.
  <div id="one">one</div>
  <div id="two">two</div>
  <div id="three">three</div>
</div>  

Ответ №1:

Если вы нажмете на контейнер, вы перезаписываете его содержимое, включая дочерние подразделения и их обработчики событий. Не используйте .innerHTML для этого. Используйте .insertAdjacentHTML() вместо этого.

 function callback(e) {
    this.insertAdjacentHTML('beforeend', '<br/>'   e.type   ' on '   e.target.nodeName   '#'   e.target.id);
    console.log(this);
    e.stopPropagation();
}

document.querySelectorAll('div').forEach(function(div, i) {
    div.addEventListener('click', callback, false);
});  
 #container { border: 1px solid #ddd; padding: 10px; background: #fcfcfc; }
#container div { width: 200px; min-height: 50px; border: 1px solid #ccf; margin:5px; padding: 10px; background: #eef; }  
 <div id="container">
  I am the container.
  <div id="one">one</div>
  <div id="two">two</div>
  <div id="three">three</div>
</div>  

Комментарии:

1. Спасибо, я собираюсь биться головой о стену.

Ответ №2:

вы можете использовать element.append() вместо element.innerHTML для решения вашей проблемы. поскольку innerHTML будут удалены все дочерние узлы, затем создайте дочерние узлы нового экземпляра, чтобы все прослушиватели событий были удалены

 function callback(e) {
    this.append(` ${e.type} on ${e.target.nodeName} ${e.target.id} `)
    console.log(this);
    e.stopPropagation();
}

document.querySelectorAll('div').forEach(function(div, i) {
    div.addEventListener('click', callback, false);
});  
 #container { border: 1px solid #ddd; padding: 10px; background: #fcfcfc; }
#container div { width: 200px; min-height: 50px; border: 1px solid #ccf; margin:5px; padding: 10px; background: #eef; }
</style>  
 <div id="container">
  I am the container.
  <div id="one">one</div>
  <div id="two">two</div>
  <div id="three">three</div>
</div>  

Комментарии:

1. Спасибо, я собираюсь биться головой о стену.