DEV Community

Cover image for How to use MutationObserver.observe() instead of setTimeOut()
Rae Liu
Rae Liu

Posted on • Updated on

How to use MutationObserver.observe() instead of setTimeOut()

Why not to use setTimeOut?

I used to use setTimeOut to wait until the entire JS codes are loaded so I can change the DOM.
But setTimeOut is unstable because JS loading time depends on browser type, internet speed and other factors. So how many seconds you should wait? It might work for your computer, but not for others...

What is MutationObserver

MutationObserver is a useful api that can observe DOM changes, and it also supports IE11!
Alt Text

Basic Syntax - observer()

Here is a sample HTML -

  <ul class='myList'>
    <li>LCD writing board</li>
    <li>Paper</li>
    <li>
       Tablet
       <ul class='tabletList'>
          <li>IPAD</li>
          <li>Samsung Galaxy Tab </li>
       </ul>
    </li>
  </ul>
Enter fullscreen mode Exit fullscreen mode
//identity an element to observe
const myListObserver = document.querySelector(".myList");

//a callback that runs when the observer is triggered
const observer = new MutationObserver(function() {
    console.log('trigged');
});
//passing element to observer function, and `options`
observer.observe(myListObserver, {OPTIONS_OBJECT});

Enter fullscreen mode Exit fullscreen mode

Options Object

Options decides when to trigger the callback -
Options List -

let Options = {
  childList: bool,
  attributes: bool,
  characterData: bool,
  subtree: bool,
  attributeFilter: array,
  attributeOldValue: bool,
  characterDataOldValue: bool,
}
Enter fullscreen mode Exit fullscreen mode

Note: One of childList, attributes, and/or characterData must be true when you call observe().

1. Options - childList

observer.observe(myListObserver, {childList: true});
Enter fullscreen mode Exit fullscreen mode

The callback is only triggered when immediate children nodes are added or removed.
In example HTML, if anything in .tabletList(nested list) is changed, then it won't trigger the callback.

2. Options - subtree

observer.observe(myListObserver, {childList: true, subtree: true});
Enter fullscreen mode Exit fullscreen mode

The callback will be triggered when any child nodes inside .myList is added or removed.

3. Options - attributes and attributeFilter

observer.observe(myListObserver, {attribute: true});
Enter fullscreen mode Exit fullscreen mode

Execute callback when any attribute is changed

observer.observe(myListObserver, {attribute: true, attributeFilter:['class', 'style']});
Enter fullscreen mode Exit fullscreen mode

Execute callback when class name or style is changed.

For example, if .tabeltList changes name, then the callback will be triggered.

Here is the attributes list at w3schools.

4. Options - characterData

  <ul class='myList'>
    <li>LCD writing board</li>
    <li>Paper</li>
    <li>
       Tablet
       <ul class='tabletList'>
          <li>IPAD</li>
          <li>Samsung Galaxy Tab </li>
       </ul>
    </li>
  </ul>
Enter fullscreen mode Exit fullscreen mode
observer.observe(myListObserver, {childList: true, subtree: false, characterData: true});
Enter fullscreen mode Exit fullscreen mode

It will execute callback if I change Paper text.

observer.observe(myListObserver, {subtree: true, childList: false, characterData: true});
Enter fullscreen mode Exit fullscreen mode

It will execute callback if I change IPAD text.

5. Options - attributeOldValue, characterDataOldValue

Set to true to record previous value so callback can use.
Note:attributes will be automatically set to true if attributeOldValue is true. characterData and characterDataOldValue are as same as the attribute ones.

Callback

We can loop every element in mutations

const observer = new MutationObserver(function(mutations) {
    for (let mutation of mutations) {
     case 'childList':
        break;
     case 'attributes':
        console.log(mutation.oldValue) //if attributeOldValue == true
        break;
     case: 'characterData':
        console.log(mutation.oldValue) //if characterDataOldValue == true
        break;
    }
});
Enter fullscreen mode Exit fullscreen mode

Using the disconnect() method

observer.disconnect();
Enter fullscreen mode Exit fullscreen mode

Stop to watch for mutations.
If we don't use disconnect(), then the watching will never stop, and might cause some memory problems.

Discussion (1)

Collapse
ozcantaga profile image
ozcantaga

ı like it thanks sweet girl