Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why can event listeners stop working after using element.innerHTML?

I am a beginner in JavaScript. A JavaScript book says that one of disadvantages of element.innerHTML is:

Event handlers may no longer work as intended.

I can't understand what this mean. Can someone give me an example?

like image 992
Micheal_Song Avatar asked May 25 '16 22:05

Micheal_Song


People also ask

Does innerHTML remove event listeners?

Please note that using innerHTML to append HTML elements (e.g. el.innerHTML += "<a href='…'>link</a>" ) will result in the removal of any previously set event listeners. That is, after you append any HTML element that way you won't be able to listen to the previously set event listeners.

Do event listeners get removed when element is removed?

In modern browsers, if a DOM Element is removed, its listeners are also removed from memory in javascript. Note that this will happen ONLY if the element is reference-free. Or in other words, it doesn't have any reference and can be garbage collected. Only then its event listeners will be removed from memory.

Why innerHTML does not work?

People can struggle and complain about innerHTML not working. Such things usually occur because of human error, when strings are not appropriately defined, or there are some mistakes in JavaScript code.

Do event listeners only work once?

We can pass an object as an argument to the addEventListener method and specify that the event is only handled once. This is achieved by passing the property once to the object. If we set once to true, the event will only be fired once.


2 Answers

Most probably, it refers to the technique some people use to insert HTML at the end:

element.innerHTML += "inserted HTML";

This will get the current HTML, concatenate it with the inserted one, and parse it all.

As a side effect, all the internal state of the existing elements (like event listeners, checkedness, ...) will be lost.

var btn = document.querySelector("button");
btn.addEventListener("click", function() {
  btn.textContent = "I won't work anymore";
  document.body.innerHTML += "<p>Inserted text</p>";
});
<button>Click me to insert HTML</button>

Instead, if you want to insert some HTML at the end of an element, you can use

element.insertAdjacentHTML('beforeend', "inserted HTML");

This will preserve the existing elements.

var btn = document.querySelector("button");
btn.addEventListener("click", function() {
  btn.textContent = "I still work";
  document.body.insertAdjacentHTML("beforeend", "<p>Inserted text</p>");
});
<button>Click me to insert HTML</button>

Another alternative, if you don't mind the inserted content to be wrapped inside an element, is using appendChild:

var btn = document.querySelector("button");
btn.addEventListener("click", function() {
  btn.textContent = "I still work";
  var wrapper = document.createElement('div');
  wrapper.innerHTML = "<p>Inserted text</p>";
  document.body.appendChild(wrapper);
});
<button>Click me to insert HTML</button>
like image 189
Oriol Avatar answered Oct 10 '22 17:10

Oriol


innerHTML is a string representation of html contents of an element. Getting these contents has no side effect but resetting it force the browser to generate new elements.

Each HTML tag in a document is parsed as an unique DOM HTMLElement object by the browsers. Event handlers are bound to these elements. By resetting innerHTML property, browser removes the old elements and makes the DOM parser to create other element objects based on the new html string. When an element is removed it's event handlers are also removed.

Imagine that you have an element that responds to it's click events via a handler, when the element is removed you can't click on it so it makes you feel the handler is also removed. The way event handlers are garbage collected depends on the code that has been written and the way a JavaScript interpreter works.

like image 38
undefined Avatar answered Oct 10 '22 18:10

undefined