#CodeNewbie

#CodingTips

#Frontend

#Fullstack

#JavaScript

#LearnToCode

#Programming

#WebDevelopment

MutationObserver — watching DOM changes

MutationObserver detects when the DOM changes — elements added, removed, text modified, or attributes changed. Instead of polling the DOM repeatedly, use MutationObserver to react immediately to changes. Perfect for tracking dynamic content, monitoring third-party scripts, and handling dynamically inserted elements.


 

The old way: polling the DOM

// ❌ Polling: inefficient, wasted resources
setInterval(() => {
  const newElements = document.querySelectorAll(".dynamic-item:not(.processed)");
  
  newElements.forEach(el => {
    processElement(el);
    el.classList.add("processed");
  });
}, 500);  ← checks every 500ms, even if nothing changed

// Problems:
// - Wastes CPU checking frequently
// - Delays: changes not detected immediately
// - Complex to implement correctly

 

MutationObserver — the efficient way

// ✅ MutationObserver: react immediately to changes
const observer = new MutationObserver((mutations) => {
  mutations.forEach(mutation => {
    if (mutation.type === "childList") {
      // Element added or removed
      mutation.addedNodes.forEach(node => {
        if (node.classList?.contains("dynamic-item")) {
          processElement(node);
        }
      });
    }
    
    if (mutation.type === "attributes") {
      // Attribute changed
      console.log(`${mutation.attributeName} changed`);
    }
  });
});

const config = {
  childList: true,        ← watch for added/removed elements
  subtree: true,          ← watch all descendants
  attributes: true         ← watch attribute changes
};

observer.observe(document.body, config);

// Later: stop observing
observer.disconnect();

 

Real-world examples

Detecting dynamically added content

// Example: JavaScript framework adds elements dynamically
const observer = new MutationObserver((mutations) => {
  mutations.forEach(mutation => {
    mutation.addedNodes.forEach(node => {
      if (node.nodeType === 1) {    ← element node
        console.log("New element:", node.tagName);
        initializeElement(node);
      }
    });
  });
});

observer.observe(document.body, { childList: true, subtree: true });

Monitoring text content changes

const observer = new MutationObserver((mutations) => {
  mutations.forEach(mutation => {
    if (mutation.type === "characterData") {
      console.log("Text changed:", mutation.target.textContent);
    }
  });
});

const config = {
  characterData: true,    ← watch text node changes
  subtree: true,
  characterDataOldValue: true  ← capture old value
};

observer.observe(element, config);

 

Key takeaways

MutationObserver detects DOM changes without polling. Pass configuration options: childList (elements added/removed), attributes (attribute changes), characterData (text changes), and subtree (watch descendants). mutation.addedNodes contains newly added elements. Always call observer.disconnect() when done to prevent memory leaks. Use MutationObserver for frameworks that add content dynamically, monitoring third-party scripts, or watching user interactions that modify the DOM.