MutationObserver — DOM o'zgarishlarini kuzatish

~15 daq · JavaScript · Brauzer API lari

Muammodan boshlaylik

Uchinchi tomon kutubxonasi ishlatmoqdasiz — siz uning kodini o'zgartira olmaysiz. Lekin u DOM ga ma'lum element qo'shganda, siz bilib, unga CSS qo'llashingiz kerak.

Yoki foydalanuvchi dinamik qo'shilgan elementni tahrirladi — siz darhol bilishingiz kerak.

Oddiy hodisalar (click, input) bu holat uchun ishlamaydi — DOM o'zgarishi hodisa emas, brauzer signal bermaydi.

Eski usul — setInterval bilan har 100ms da DOM ni tekshirish. Bu isrof va kechikish bor.

MutationObserver — DOM da o'zgarish bo'lganda brauzer o'zi xabar beradi.


MutationObserver nima?

MutationObserver — DOM daraxtidagi o'zgarishlarni kuzatish vositasi. Element qo'shilsa, o'chirilsa, atributi o'zgarsa, matni o'zgarsa — observer ishga tushadi.

Hayotiy o'xshatma

Omborxona xodimi. U omborni doim kuzatib turadi. Yangi mahsulot kelsa — yozadi. Mahsulot chiqqanda — yozadi. Mahsulotning nomi o'zgarsa — yozadi. U hisobot kitobchasi bilan o'tirib, har bir o'zgarishni qayd etadi.

MutationObserver — o'sha omborxona xodimi. DOM — ombor. Har o'zgarishda sizga xabar beradi.


Asosiy ishlatilish

const kuzatuvchi = new MutationObserver(function(mutatsiyalar) {
  mutatsiyalar.forEach(function(mutatsiya) {
    console.log("O'zgarish turi:", mutatsiya.type);
    console.log("O'zgargan element:", mutatsiya.target);
  });
});

const element = document.getElementById("kuzatiladigan");

kuzatuvchi.observe(element, {
  childList:  true,  // ← bola elementlar qo'shilsa/o'chirilsa
  attributes: true,  // ← atributlar o'zgarsa
  characterData: true, // ← matn o'zgarsa
  subtree:    true,  // ← ichki barcha elementlarni ham kuzatish
});

mutatsiya.type — o'zgarish turi

Har bir mutatsiya ob'ektida type xususiyati bor:

childList — farzand element qo'shildi yoki o'chirildi. attributes — element atributi o'zgardi. characterData — matn tuguni o'zgardi.

const kuzatuvchi = new MutationObserver(function(mutatsiyalar) {
  mutatsiyalar.forEach(function(mut) {
    if (mut.type === "childList") {
      console.log("Qo'shildi:", mut.addedNodes);   // qo'shilgan elementlar
      console.log("O'chirildi:", mut.removedNodes); // o'chirilgan elementlar
    }

    if (mut.type === "attributes") {
      console.log("Atribut:", mut.attributeName);   // qaysi atribut o'zgardi
      console.log("Yangi qiymat:", mut.target.getAttribute(mut.attributeName));
    }
  });
});

Amaliy misol — uchinchi tomon kutubxonasini kuzatish

Chatbot kutubxonasi sahifaga xabar qo'shadi. Har yangi xabarda siz bildirishnoma ko'rsatmoqchisiz:

const chatKonteyner = document.getElementById("chat-xabarlar");

const kuzatuvchi = new MutationObserver(function(mutatsiyalar) {
  mutatsiyalar.forEach(function(mut) {
    if (mut.type !== "childList") return;

    mut.addedNodes.forEach(function(tugun) {
      // Faqat elementlarni tekshirish (matn tugunlari emas)
      if (tugun.nodeType !== Node.ELEMENT_NODE) return;

      if (tugun.classList.contains("kiruvchi-xabar")) {
        bildirishnomaChaqqir("Yangi xabar keldi!");
      }
    });
  });
});

kuzatuvchi.observe(chatKonteyner, {
  childList: true, // ← faqat farzandlar qo'shilsa/o'chirilsa
});

Kuzatishni to'xtatish

kuzatuvchi.disconnect(); // ← kuzatishni to'xtatish

Kuzatish kerak bo'lmay qolganida — disconnect. Aks holda kuzatuvchi ishlashda davom etadi va xotira sarflanadi.


subtree — ichki elementlarni ham kuzatish

Odatda faqat to'g'ridan bola elementlar kuzatiladi. subtree: true bilan — barcha avlodlar:

kuzatuvchi.observe(document.body, {
  childList: true,
  subtree: true, // ← body ichidagi istalgan joyda o'zgarish bo'lsa
});

Katta daraxtlarda subtree: true qimmat operatsiya bo'lishi mumkin — faqat kerak bo'lganda ishlatiladi.


Tez-tez uchraydigan xatolar

O'zgarish ichida yana o'zgarish — cheksiz loop:

Observer DOM o'zgarishlarini kuzatadi. Agar observer ichida DOM o'zgartirilsa — observer qayta ishlaydi. Bu cheksiz loop hosil qilishi mumkin.

// ❌ — cheksiz loop
kuzatuvchi.observe(el, { childList: true });

new MutationObserver(function() {
  el.appendChild(document.createElement("div")); // ← yana o'zgarish → yana callback
});

// ✅ — kuzatishni to'xtatib, o'zgartirib, qayta boshlash
new MutationObserver(function(mutatsiyalar) {
  kuzatuvchi.disconnect(); // ← to'xtatish
  el.appendChild(document.createElement("div")); // ← o'zgartirish
  kuzatuvchi.observe(el, { childList: true });   // ← qayta boshlash
});

disconnect unutish:

Component o'chirilganda observer ham to'xtatilishi kerak. Aks holda to'xtalib qolgan DOM elementlarini kuzatishda davom etadi.


Xulosa

MutationObserver — DOM o'zgarishlarini kuzatish. Element qo'shilsa, o'chirilsa, atribut o'zgarsa — observer biladi.

Uch tur: childList (farzandlar), attributes (atributlar), characterData (matn).

subtree: true — barcha ichki elementlarni ham kuzatish.

disconnect() — kuzatishni to'xtatish. Keraksiz kuzatuvchi — xotira isrof.

Intersection Observer — element ko'rinyaptimi. MutationObserver — DOM o'zgardimi. Har biri o'z vazifasida.


Keyingi dars

54-dars: ES Modullar — import, export, re-export