Observe changes in DOM using MutationObserver

March 28, 2018 0 Comments

Observe changes in DOM using MutationObserver



In this article, we’ll look at the mutation observer API. Why do we need it and how to use it.

Let’s start with the purpose for which it can be used. As you can already guess from the title of the article, it is used to monitor changes in the DOM. For such as — adding new nodes, deleting them or changing their attributes, text data.

Observer useful when you want to handle specific changes in your DOM in an efficient way, without using a virtual DOM or relooking throughout the structure with a timeout function.

The most important thing to observe for changes is to create a subscriber. This is a function that will be called every time something changes in the DOM. In other words, it subscribes to changes.

What we see here is that the subscriber is just a function with one argument (you can also specify a second argument for the observer instance). This argument (mutations) is a JavaScript array with all its methods, so we can use the forEach() method to iterate through the mutations. Even if there is only one change in DOM mutations will still be an array, but with only one element — MutationRecord. As you can see, MutationRecord is not just an object, it has its own constructor. In more detail we will look at it later. But now let’s focus on the mutations array.

So why do we get an array instead of a single MutationRecord. The answer here is that MutationObserver works asynchronously. For example, if you change three items in the DOM at the same time — the subscriber will be called only once, but with three mutations, and each will represent each change you made. But if these elements change at different times, for example, with 1 second delay, the subscriber will be called three times with one mutation each time.

Why does it work like that? Because it is much more efficient in performance than the synchronous way, and will not block DOM mutations if we change it through JavaScript.

Time to move forward! Now it’s time to create an observer.

To create an instance of observer, we need to create it using the MutationObserver constructor with one parameter — the subscriber function. But the code above will not immediately observe our document. For this to work, we have to do three more things. Let’s do it step by step to achieve our goal.

The target element can be any DOM node. If you only want to monitor changes on a particular item, you can select it using the regular getElement(s)by…, querySelector or whatever you use. If you want to monitor changes to the entire document, you can specify target as just a document, remember that the window is not a DOM element, so do not specify it.

At the moment we’ve done the function of the subscriber, specify target and construct our observer. Now it’s time to configure it! Here is an important step that we cannot ignore because otherwise the entire observer will not work. Why config is so important? It indicates what the observer should look for and what we will then get in the subscriber.

Here’s what a config object looks like with all its properties.

By default, all configuration properties are set to false, and without specifying any of them, you get an error when you try to create an observer. Because observer should know what type of mutations you are looking for.

You can choose as many configuration properties as you want. But at least you have to specify one of — childList, attributes or characterData should be set to true. If you don’t know what CharacterData is, you can read about it on MSDN. In short, in most cases it’s — text nodes.

Finally, to observe the changes, we need to call observer with the observe method, which takes two parameters — target element and config.

The code above is sufficient to find changes to the DOM, such as adding or removing new nodes, adding/modifying/deleting attributes, and modifying text data. Thus, we can observe changes in our document completely.

But there is another important thing — we need to understand the data that we receive in the subscriber.

It’s time to take a look at the mutation object we’re getting. As mentioned earlier, it has its own MutationRecord constructor.

MutationRecord will always contain all of its 9 properties, but if you do not specify some of them in config, these values will be null.

Now, for example, let’s imagine that we have some kind of div element with text child elements, and we want to make sure that any change to the text itself doesn’t have more than five characters, otherwise we’ll set it to “too long”.

Here we use two properties — addedNodes and target. Important note — if we set innerText to mutation target within the subscriber, the observer will not be triggered then.

Now let’s look at two more methods that the observer has.

Disconnect method — simply stops the observer from getting any mutation events. TakeRecords method empties the instance of the observer and returns the records.

In this last section, we’ll look at an example of how to use observer mutation. Here is a pop-up alert notifies us of attribute changes.

So, in this article, we looked at why and how to use MutationObserver. I hope this was helpful and now you have a better understanding of this API.

Tag cloud