Wzorzec obserwatora jest bardzo prosty. W swoim założeniu polega na tym, że jeden obiekt powiadamia inne obiekty o swojej zmianie. W JavaScript istnieją predefiniowane observators, które ułatwiają życie programistom.
MutationObserver
Pozwala na śledzenie zmian, takich jak zmiana atrybutów czy dodanie nowego węzła w strukturze DOM.
Konstruktor klasy MutationObserver przyjmuje jako parametr callback. Callback z kolei otrzyma tablicę z obiektami MutationRecord oraz jako drugi parametr instancję MutationObserver.
Aby rozpocząć obserwację, należy wywołać metodę observe, która jako argumenty przyjmuje Node (np. HTMLElement) oraz konfigurację.
Przykład
Załóżmy, że mamy pole tekstowe i chcemy zliczać ilość znaków.
function mutationObserverCallback(mutations) {
mutations.forEach((mutation) => {
if (mutation.type === 'characterData') {
updateCounter(mutation.target.value.length);
}
});
}
function updateCounter(length) {
document.getElementById('char-counter')?.innerText = length;
}
const observeConfig = {
characterData: true,
};
(new MutationObserver(mutationObserverCallback))
.observe(document.getElementById('text-area'), observeConfig);
Code language: JavaScript (javascript)
Przy wprowadzaniu tekstu do textarea
za każdym razem będzie aktualizowana wartość w elemencie #char-counter
.
IntersectionObserver
Stałym problemem we frontend developmencie od zawsze było ustalenie, czy dany element jest widoczny w obszarze użytkownika, czy nie. Stara szkoła uczyła, aby nasłuchiwać zdarzenia scroll
, a następnie ustalać przesunięcie elementu względem góry dokumentu i przesunięcia. Było to obciążające zadanie, zwłaszcza gdy musieliśmy śledzić wiele takich elementów w ogromnej strukturze DOM. Ten problem rozwiązuje IntersectionObserver.
Podobnie jak inne interfejsy, konstruktor IntersectionObserver przyjmuje Callback, który reaguje na zmiany oraz konfigurację. Callback przyjmuje tablicę IntersectionObserverEntry oraz instancję obserwatora.
Do uruchomienia obserwacji służy metoda observe, która jako argument przyjmuje obiekt dziedziczący po Element.
Przykład
Załóżmy, że chcemy wykrywać elementy .ad
, w których występują reklamy.
function itersectionObserverCallback(entries) {
entries.forEach(entry => {
if (entry.isIntersecting) {
console.log('Element jest widoczny');
} else {
console.log('Element jest poza obszarem widzenia');
}
});
}
// konfiguracja domyślna
const observer = new IntersectionObserver(itersectionObserverCallback);
document.querySelectorAll('.ad').forEach(element => observer.observe(element));
Code language: JavaScript (javascript)
Kod wybierze wszystkie elementy z klasą .ad
i zacznie je obserwować. Gdy znikną lub pojawią się na ekranie, w konsoli zostanie zalogowany odpowiedni komunikat.
ResizeObserver
Ostatnim prezentowanym dzisiaj obserwatorem jest ResizeObserver i służy do obserwowania rozmiaru elementu. Chociaż większość zadań związanych z rozmiarem można wykonać za pomocą media query
, czasem istnieją specyficzne przypadki, kiedy ResizeObserver znajdzie zastosowanie.
Konstruktor jako parametr otrzymuje Callback, który przyjmuje dwa argumenty: tablicę z ResizeObserverEntry oraz instancję obserwatora.
Do zainicjowania obserwacji służy metoda observe, która jako argument przyjmuje obiekt dziedziczący po Element oraz konfigurację. W chwili pisania tego artykułu, konfiguracja ma tylko jedną właściwość box z możliwymi parametrami: border-box, content-box, device-pixel-content-box
.
Przykład
Załóżmy, że na stronie znajdują się reklamy, które są pobierane dynamicznie. Zanim zostaną pobrane i wyświetlany jest obraz zastępczy. Chcemy dynamicznie zamieniać obraz zastępczy z prawdziwą reklamą.
function resizeObserverCallback(entries, observer) {
entries.forEach(entry => {
if (entry.contentRect.height > 20) {
entry.target.nextElementSibling.remove();
observer.unsubscribe(entry.target);
}
});
}
const observer = new ResizeObserver(resizeObserverCallback);
document.querySelectorAll('.ad').forEach(element => observer.observe(element));
Code language: JavaScript (javascript)
Jeśli reklama będzie miała wysokość większą niż 20px
, wtedy zostanie usunięty element występujący po nim. W naszym przykładzie jest to domyślna reklama. Zadbaliśmy również o zaprzestanie obserwacji na elemencie .ad
, gdy reklama zostanie wyświetlona.
Podsumowanie
Observators w JavaScript to potężne narzędzia, które pozwalają wprowadzić jeszcze lepszą interakcję z stroną internetową. Jednak niewłaściwe lub nadmierne ich stosowanie może pogorszyć wydajność. Dlatego powinny być stosowane z ostrożnością, a konfiguracja powinna być dostosowana do wymagań.