📜 ⬆️ ⬇️

DOM MutationObserver - reacting to a change in DOM without killing browser performance

DOM Mutation Events at one time seemed like a great idea - web developers began to create more dynamic applications, and it seemed natural the joy with which new opportunities to listen to DOM changes and respond to them were met. In practice, however, it turned out that DOM Mutation Events has serious performance and stability issues. Not surprisingly, the specification got the status “obsolete” a year later.

But the very idea behind DOM Mutation Events seemed attractive and therefore, in September 2011, a group of Google and Mozilla engineers presented a proposal for DOM MutationObserver , with similar functionality, but improved performance. This new DOM-API is available starting from versions: Firefox 14, Chrome 18, IE 11, Safari 6 (other browsers are caniuse.com/mutationobserver )

In the simplest case, MutationObserver is used like this:

//   var target = document.querySelector('#some-id'); //    var observer = new MutationObserver(function(mutations) { mutations.forEach(function(mutation) { console.log(mutation.type); }); }); //   var config = { attributes: true, childList: true, characterData: true } //       observer.observe(target, config); //     observer.disconnect(); 

A key advantage of the new specification over the outdated DOM Mutation Events is efficiency. When you monitor a DOM node, your callback function will not work until the DOM changes are complete. When the callback works, it will be passed to the final list of changes to the DOM, running through which you can somehow respond to the changes.
')
It is also assumed that the code will need to somehow process the results transmitted by the observer in order to respond to the changes we need. Here is a small example of an observer listening for changes to an edited on-site ordered list:

 <!DOCTYPE html> <ol contenteditable oninput=""> <li>Press enter</li> </ol> <script> var MutationObserver = window.MutationObserver || window.WebKitMutationObserver || window.MozMutationObserver; var list = document.querySelector('ol'); var observer = new MutationObserver(function(mutations) { mutations.forEach(function(mutation) { if (mutation.type === 'childList') { var list_values = [].slice.call(list.children) .map( function(node) { return node.innerHTML; }) .filter( function(s) { if (s === '<br>') { return false; } else { return true; } }); console.log(list_values); } }); }); observer.observe(list, { attributes: true, childList: true, characterData: true }); </script> 

So that you can see the code in the case, I posted it on jsbin:

jsbin.com/ivamoh/53/edit

If you play around with the code in the sandbox, you probably noticed one feature: the callback function only works when you press “enter” on any element of the list - essentially, this is because your actions lead to add or remove a DOM node. This is the most important difference from other techniques, such as subscribing to keystrokes, or mouse clicks. MutationObservers does not work in the same way as all these techniques - here the triggering occurs only when the DOM is changed, and not as a reaction to events initiated by JS, or user actions.

So, where is it used?

I do not think that all programmers immediately and for no reason at all, they abandon everything, and start embedding MutationObservers into their code. Probably most of all, this API is suitable for developers of JS frameworks to implement something new, or something that was not previously implemented due to performance problems. Also, this technique is useful if you use any framework that modifies the DOM, and you need to respond to these changes (without the use of crutches, such as setTimeout). Well, the last thing is the development of browser extensions.

Resources:


From the translator: the material is more than a year old, but something is too little in Russian about MutationObserver - can someone come in handy.

Source: https://habr.com/ru/post/202366/


All Articles