Intersection Observer — lazy loading uchun
Muammodan boshlaylik
Sahifada 100 ta rasm bor. Foydalanuvchi hozir faqat birinchi 5 tasini ko'radi — qolgan 95 tasi ekran ostida. Lekin sahifa yuklanayotganda barchasi yuklandi: 100 ta rasmga 100 ta HTTP so'rov ketdi.
Bu muammolar tug'diradi:
- Sahifa sekin yuklanadi — katta fayllar ko'p
- Foydalanuvchi hech qachon pastga tushmasligi mumkin — 95 ta rasm behuda yuklandi
- Mobil internetda — trafik sarflanadi
Yechim — lazy loading: rasm ekranga ko'rinib qolganida yuklansin, oldin emas.
Buni qanday qilish mumkin? Eski usul — scroll hodisasini tinglash, har scrollda rasmlar pozitsiyasini hisoblash. Bu juda sekin va brauzer yuklanadi.
Intersection Observer — zamonaviy va samarali yechim.
Intersection Observer nima?
Intersection Observer — brauzerga "mana bu element ko'rinib qolsa menga ayt" deb buyurish usuli. Brauzer o'zi kuzatadi — siz hisoblashmaysiz.
Hayotiy o'xshatma
Ko'cha devoriga reklama taxtasi o'rnatilgan. Reklama beruvchi bilmoqchi: "qancha odam bu taxtani ko'rdi?" Eski usul — odamlarni sanash uchun biror joyda turib hisoblash. Yangi usul — sensor o'rnatish: odam yaqinlashganda sensor o'zi signal beradi, reklama beruvchi biladi.
Intersection Observer — o'sha sensor. Siz o'rnatib qo'yasiz, brauzer o'zi kuzatadi.
Asosiy ishlatilish
const kuzatuvchi = new IntersectionObserver(function(yozuvlar) {
yozuvlar.forEach(function(yozuv) {
if (yozuv.isIntersecting) {
// ← element ko'rindi
console.log("Ko'rindi:", yozuv.target);
}
});
});
const element = document.querySelector(".kuzatiladigan");
kuzatuvchi.observe(element); // ← kuzatishni boshlash
isIntersecting — element viewport da ko'rinadimi? true — ko'rinyapti.
Lazy loading — amaliy misol
HTML da rasmlar avval yuklanmaydi — data-src atributiga manzil yoziladi, src bo'sh qoladi:
<img data-src="/rasmlar/tog.jpg" alt="Tog'" class="lazy-rasm">
<img data-src="/rasmlar/daryo.jpg" alt="Daryo" class="lazy-rasm">
<img data-src="/rasmlar/sahro.jpg" alt="Sahro" class="lazy-rasm">
JavaScript — rasm ko'ringanda haqiqiy src ga o'tkazadi:
const kuzatuvchi = new IntersectionObserver(function(yozuvlar) {
yozuvlar.forEach(function(yozuv) {
if (!yozuv.isIntersecting) return; // ← ko'rinmayotgan bo'lsa — e'tiborsiz
const rasm = yozuv.target;
rasm.src = rasm.dataset.src; // ← haqiqiy src qo'yildi — brauzer yuklaydi
kuzatuvchi.unobserve(rasm); // ← rasm yuklandi, endi kuzatish shart emas
});
});
// Barcha lazy rasmlarni kuzatishga qo'shish
document.querySelectorAll(".lazy-rasm").forEach(function(rasm) {
kuzatuvchi.observe(rasm);
});
Nima uchun unobserve kerak?
Rasm bir marta yuklandidan keyin uni kuzatishda davom etish shart emas. unobserve — kuzatuvchidan olib tashlash. Bu resurslarni tejaydi.
rootMargin — oldindan yuklash
Foydalanuvchi pastga tushayotganda — rasm ko'rinib qolguncha kutish kerak emas. Biroz oldinroq — "ekranga 200px qolganida" yuklanishni boshlash yanada qulay.
const kuzatuvchi = new IntersectionObserver(
function(yozuvlar) {
yozuvlar.forEach(function(yozuv) {
if (!yozuv.isIntersecting) return;
yozuv.target.src = yozuv.target.dataset.src;
kuzatuvchi.unobserve(yozuv.target);
});
},
{
rootMargin: "200px", // ← element ko'rinishdan 200px oldin signal
}
);
Foydalanuvchi hali etib kelmagan — rasm esa allaqachon yuklanib bo'ldi. Ko'zgacha uzluksiz ko'rinish.
threshold — qancha ko'ringanda
threshold — elementning qancha qismi ko'ringanda signal berish. 0 dan 1 gacha.
const kuzatuvchi = new IntersectionObserver(
function(yozuvlar) { ... },
{
threshold: 0.5, // ← element 50% ko'ringanda signal
}
);
threshold: 0 // ← bir piksel ko'ringanda (standart)
threshold: 0.5 // ← yarmidan ko'pi ko'ringanda
threshold: 1 // ← to'liq ko'ringanda
threshold: [0, 0.25, 0.5, 0.75, 1] // ← har bir chegarada signal
"Infinity scroll" — pastga tushganda yangi ma'lumot
Lazy loading dan tashqari, Intersection Observer "infinity scroll" uchun ham ishlatiladi. Ro'yxat oxiriga kelganda yangi ma'lumot yuklanadi.
const yuklovchi = document.getElementById("yuklovchi"); // ro'yxat oxiridagi element
const kuzatuvchi = new IntersectionObserver(async function(yozuvlar) {
if (!yozuvlar[0].isIntersecting) return;
kuzatuvchi.unobserve(yuklovchi); // ← kuzatishni to'xtatib
const yangilar = await keyingiSahifaOl(); // ← yangi ma'lumot olish
ro_yxatgaQosh(yangilar);
kuzatuvchi.observe(yuklovchi); // ← yana kuzatishni boshlash
});
kuzatuvchi.observe(yuklovchi);
Tez-tez uchraydigan xatolar
Yuklanib bo'lgan rasmni qayta yuklashga urinish:
// ❌ — src allaqachon to'g'ri, lekin unobserve unutildi
// Observer qayta ishlaydi, src qayta o'rnatiladi
kuzatuvchi.observe(rasm);
// ✅ — yuklangandan keyin unobserve
if (!yozuv.isIntersecting) return;
rasm.src = rasm.dataset.src;
kuzatuvchi.unobserve(rasm); // ← muhim
Rasm yuklanmay qolishi — data-src yo'q:
// ❌ — data-src atributi yo'q
const rasm = document.createElement("img");
rasm.alt = "Rasm";
// data-src qo'yilmadi
// ✅
rasm.dataset.src = "/rasmlar/manzara.jpg";
rasm.alt = "Manzara";
Xulosa
Intersection Observer — element viewport da ko'rinyaptimi kuzatuvchi. scroll hodisasidan tez va qulay.
Lazy loading — rasm ko'ringanda yuklash. data-src → src o'tkazish. Yuklanganida unobserve.
rootMargin — element ko'rinishdan N px oldin signal. Oldindan yuklash uchun.
threshold — elementning qancha qismi ko'ringanda signal berish.
Keyingi dars
53-dars: MutationObserver — DOM o'zgarishlarini kuzatish