مقدمه
بسیاری از تعاملات ما با DOM به صورت دستوری (imperative) است؛ یعنی ما به صراحت به مرورگر میگوییم
چه کاری انجام دهد. اما در وب اپلیکیشنهای مدرن، اغلب نیاز داریم تا به تغییراتی که در DOM رخ
میدهد، واکنش (react) نشان دهیم. Observable APIs مجموعهای از رابطهای برنامهنویسی هستند که
به ما اجازه میدهند تغییرات خاصی را در DOM "مشاهده" کرده و به محض وقوع، یک تابع را اجرا کنیم.
این روش بسیار بهینهتر از بررسی مداوم و دستی (polling) وضعیت DOM است. در این درس با دو مورد از
مهمترین این APIها آشنا میشویم: MutationObserver و IntersectionObserver.
رهگیری تغییرات DOM با MutationObserver
MutationObserver یک API مدرن برای مشاهدهی تغییرات در درخت DOM است. این تغییرات میتواند شامل
افزودن یا حذف گرههای فرزند، تغییر در اتریبیوتهای یک گره، یا تغییر در محتوای یک گره متنی باشد.
این API جایگزین متدهای قدیمی و منسوخ شدهی Mutation Events شده است که مشکلات عملکردی جدی
داشتند.
روند کار با آن شامل سه مرحله است: ابتدا یک تابع callback تعریف میکنیم که هنگام بروز تغییرات
اجرا شود. سپس یک نمونه از MutationObserver با آن callback میسازیم. در نهایت، متد observe() را روی آن نمونه فراخوانی کرده و گره هدف به همراه یک شیء
پیکربندی (که مشخص میکند چه نوع تغییراتی باید رهگیری شوند) را به آن پاس میدهیم.
JAVASCRIPT
const list = document.getElementById('my-list');
const callback = function(mutationsList, observer) {
for(const mutation of mutationsList) {
if (mutation.type === 'childList') {
console.log('A child node has been added or removed.');
}
}
};
const observer = new MutationObserver(callback);
const config = { childList: true, subtree: true };
observer.observe(list, config);
setTimeout(() => list.appendChild(document.createElement('li')), 1000);
در این کد، ما یک `observer` ایجاد میکنیم که تغییرات در لیست فرزندان (childList) عنصر
list را مشاهده میکند. یک ثانیه بعد، یک <li> جدید به لیست اضافه میشود و بلافاصله
تابع callback ما اجرا شده و پیام را در کنسول ثبت میکند.
رهگیری نمایان شدن عناصر با IntersectionObserver
یکی از چالشهای رایج در توسعه وب، فهمیدن این است که چه زمانی یک عنصر وارد محدوده دید کاربر
(viewport) میشود. IntersectionObserver یک API بسیار کارآمد برای حل همین مشکل است. کاربردهای
اصلی آن شامل بارگذاری تنبل (lazy-loading) تصاویر و ویدئوها، پیادهسازی اسکرول بینهایت (infinite
scrolling)، و اجرای انیمیشنها هنگام نمایان شدن عناصر است.
روش کار با آن بسیار شبیه به MutationObserver است: یک تابع callback و یک شیء options (برای
تنظیم دقیق نحوه تقاطع) تعریف میکنیم، یک نمونه IntersectionObserver میسازیم و سپس با متد observe()، آن را روی هر عنصری که میخواهیم مشاهده کنیم، فعال
میکنیم.
JAVASCRIPT
const lazyImages = document.querySelectorAll('.lazy');
const imageObserver = new IntersectionObserver((entries, observer) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
const img = entry.target;
img.src = img.dataset.src;
img.classList.remove('lazy');
observer.unobserve(img);
}
});
});
lazyImages.forEach(img => {
imageObserver.observe(img);
});
این مثال یک الگوی رایج برای بارگذاری تنبل تصاویر را نشان میدهد. ما به IntersectionObserver
میگوییم که هر تصویر با کلاس lazy را مشاهده کند. به محض اینکه یک تصویر وارد محدوده دید
کاربر شود (isIntersecting برابر با true میشود)، ما آدرس واقعی تصویر را از
اتریبیوت data-src به اتریبیوت src منتقل کرده و سپس مشاهدهی آن تصویر را متوقف
میکنیم تا منابع بیهوده مصرف نشود.
در این درس با دو API قدرتمند برای مشاهدهی واکنشی DOM آشنا شدیم: MutationObserver برای
رهگیری تغییرات در ساختار DOM و IntersectionObserver برای تشخیص ورود و خروج عناصر از دید
کاربر. با این درس، فصل «اکستنشنهای DOM» به پایان میرسد. ما در این فصل دانش خود را با بررسی
استایلها، روشهای پیمایش مدرن، مفهوم Ranges و APIهای مشاهدهگر، عمیقتر کردیم. در فصل
بعدی، به یکی از بنیادیترین و مهمترین بخشهای جاوااسکریپت تعاملی، یعنی «رویدادها» (Events)
خواهیم پرداخت و یاد میگیریم که چگونه به تعاملات کاربر مانند کلیک، حرکت ماوس و ورودیهای کیبورد
واکنش نشان دهیم.