Usamos cookies para mejorar tu experiencia en el sitio
CodeWorlds

Zaawansowane DOM API - Obserwatory i nowoczesne interfejsy

Systemy monitoringu w Parku Jurajskim muszą reagować na zmiany w czasie rzeczywistym - pojawienie się dinozaura w strefie, zmiana rozmiaru obszaru widoczności, mutacje w strukturze danych. JavaScript oferuje zaawansowane API do obserwowania tych zmian bez konieczności ciągłego odpytywania (polling).

IntersectionObserver - obserwowanie widoczności

IntersectionObserver informuje, kiedy element wchodzi lub wychodzi z widocznego obszaru strony. Idealny do lazy loading, infinite scroll i animacji przy scrollowaniu.

1// Podstawowe użycie
2const observer = new IntersectionObserver((entries) => {
3  entries.forEach(entry => {
4    if (entry.isIntersecting) {
5      console.log(entry.target.id + ' jest widoczny');
6      entry.target.classList.add('visible');
7    } else {
8      entry.target.classList.remove('visible');
9    }
10  });
11}, {
12  threshold: 0.5,    // Wymagane 50% widoczności
13  rootMargin: '100px' // Dodatkowy margines "przed" elementem
14});
15
16// Obserwuj elementy
17document.querySelectorAll('.zone-card').forEach(card => {
18  observer.observe(card);
19});
20
21// Lazy loading obrazów
22const imageObserver = new IntersectionObserver((entries) => {
23  entries.forEach(entry => {
24    if (entry.isIntersecting) {
25      const img = entry.target;
26      img.src = img.dataset.src; // Ładuj obraz
27      imageObserver.unobserve(img); // Przestań obserwować
28    }
29  });
30});
31
32document.querySelectorAll('img[data-src]').forEach(img => {
33  imageObserver.observe(img);
34});

MutationObserver - obserwowanie zmian DOM

MutationObserver reaguje na zmiany w drzewie DOM - dodanie/usunięcie elementów, zmiana atrybutów, modyfikacja tekstu.

1// Obserwuj zmiany w kontenerze
2const mutObserver = new MutationObserver((mutations) => {
3  mutations.forEach(mutation => {
4    if (mutation.type === 'childList') {
5      mutation.addedNodes.forEach(node => {
6        if (node.nodeType === 1) { // Element
7          console.log('Dodano element:', node.tagName);
8        }
9      });
10      mutation.removedNodes.forEach(node => {
11        if (node.nodeType === 1) {
12          console.log('Usunięto element:', node.tagName);
13        }
14      });
15    }
16    if (mutation.type === 'attributes') {
17      console.log('Zmieniony atrybut:', mutation.attributeName);
18    }
19  });
20});
21
22const container = document.getElementById('dino-list');
23mutObserver.observe(container, {
24  childList: true,   // Obserwuj dodawanie/usuwanie dzieci
25  attributes: true,  // Obserwuj zmiany atrybutów
26  subtree: true      // Obserwuj też potomków
27});
28
29// Zatrzymanie obserwowania
30// mutObserver.disconnect();

ResizeObserver - obserwowanie rozmiaru

ResizeObserver reaguje na zmianę rozmiaru elementów - nie tylko okna, ale dowolnego elementu DOM.

1const resizeObserver = new ResizeObserver((entries) => {
2  entries.forEach(entry => {
3    const { width, height } = entry.contentRect;
4    console.log(entry.target.id + ':', width + 'x' + height);
5
6    // Dostosuj układ na podstawie rozmiaru
7    if (width < 400) {
8      entry.target.classList.add('compact');
9    } else {
10      entry.target.classList.remove('compact');
11    }
12  });
13});
14
15resizeObserver.observe(document.getElementById('dashboard'));

Web Storage API

localStorage i sessionStorage pozwalają przechowywać dane w przeglądarce.

1// localStorage - dane przetrwają zamknięcie przeglądarki
2localStorage.setItem('parkSettings', JSON.stringify({
3  theme: 'dark',
4  alertLevel: 3,
5  lastVisit: Date.now()
6}));
7
8const settings = JSON.parse(localStorage.getItem('parkSettings'));
9console.log(settings.theme); // 'dark'
10
11// sessionStorage - dane znikają po zamknięciu karty
12sessionStorage.setItem('currentZone', 'A');
13
14// Nasłuchiwanie zmian (między kartami!)
15window.addEventListener('storage', (event) => {
16  console.log('Zmieniono:', event.key);
17  console.log('Stara wartość:', event.oldValue);
18  console.log('Nowa wartość:', event.newValue);
19});
20
21// Usuwanie
22localStorage.removeItem('parkSettings');
23localStorage.clear(); // Usuń wszystko

Clipboard API

1// Kopiowanie tekstu
2async function copyToClipboard(text) {
3  try {
4    await navigator.clipboard.writeText(text);
5    console.log('Skopiowano:', text);
6  } catch (err) {
7    console.error('Błąd kopiowania:', err);
8  }
9}
10
11// Wklejanie tekstu
12async function pasteFromClipboard() {
13  try {
14    const text = await navigator.clipboard.readText();
15    return text;
16  } catch (err) {
17    console.error('Brak dostępu do schowka');
18  }
19}
20
21// Przycisk kopiowania z feedbackiem
22const copyBtn = document.getElementById('copy-btn');
23copyBtn.addEventListener('click', async () => {
24  const data = document.getElementById('sensor-data').textContent;
25  await copyToClipboard(data);
26  copyBtn.textContent = 'Skopiowano!';
27  setTimeout(() => copyBtn.textContent = 'Kopiuj', 2000);
28});

History API i nawigacja

1// Dodawanie wpisu do historii (bez przeładowania strony)
2history.pushState({ zone: 'A' }, '', '/park/zone-a');
3history.pushState({ zone: 'B' }, '', '/park/zone-b');
4
5// Reagowanie na przycisk "Wstecz"
6window.addEventListener('popstate', (event) => {
7  if (event.state) {
8    console.log('Powrót do strefy:', event.state.zone);
9    loadZone(event.state.zone);
10  }
11});
12
13// Zastępowanie aktualnego wpisu (bez dodawania nowego)
14history.replaceState({ zone: 'A', view: 'map' }, '', '/park/zone-a?view=map');

DocumentFragment - optymalizacja DOM

Dodawanie wielu elementów naraz jest kosztowne. DocumentFragment pozwala przygotować elementy "poza DOM" i dodać je jedną operacją:

1// BEZ fragmentu - każde appendChild powoduje reflow
2const list = document.getElementById('dino-list');
3const dinosaurs = ['Rex', 'Blue', 'Brachio', 'Stego', 'Trike'];
4
5// ZLE - 5 oddzielnych operacji DOM
6dinosaurs.forEach(name => {
7  const li = document.createElement('li');
8  li.textContent = name;
9  list.appendChild(li); // 5x reflow!
10});
11
12// DOBRZE - DocumentFragment
13const fragment = document.createDocumentFragment();
14dinosaurs.forEach(name => {
15  const li = document.createElement('li');
16  li.textContent = name;
17  fragment.appendChild(li); // Operacja "w pamięci"
18});
19list.appendChild(fragment); // 1x reflow!

"Zaawansowane DOM API to radar i systemy wczesnego ostrzegania Parku" - podsumowuje Ray Arnold. "IntersectionObserver to kamera termowizyjna, MutationObserver to system alarmowy, a ResizeObserver to adaptacyjny ekran kontrolny. Używaj ich mądrze!"

Ir a CodeWorlds