MutationObserver — DOM o'zgarishlarini kuzatish
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