Fazy przechwytywania i propagacji
Proszę zrozumieć, jak zdarzenia przemieszczają się przez DOM.
Fazy przechwytywania i propagacji to bezpłatna lekcja JavaScript Academy na CoddyKit. To lekcja 1 z 4. Możesz przeczytać całą lekcję poniżej za darmo — a potem ćwiczyć ją interaktywnie w przeglądarce z wbudowanym edytorem kodu i tutorem AI dostępnym 24/7. To część ścieżki edukacyjnej JavaScript Academy, a Twój postęp synchronizuje się między webem a aplikacją CoddyKit. Kurs JavaScript Academy zawiera 4 lekcji w sumie.
Dwie fazy przepływu przez DOM
Gdy klikają Państwo element, zdarzenie nie jest wywoływane wyłącznie na tym elemencie. Przechodzi ono przez drzewo DOM w dwóch fazach: fazie przechwytywania (z góry na dół, od document do elementu docelowego) oraz fazie propagacji w górę (z dołu do góry, od elementu docelowego z powrotem do document).
<div id="outer">
<button id="inner">Click</button>
</div>Domyślnie: propagacja w górę
Domyślnie addEventListener nasłuchuje podczas fazy propagacji w górę. Kliknięcie wewnętrznego przycisku najpierw uruchamia jego handler, następnie handler jego elementu nadrzędnego, potem handler elementu nadrzędnego wyższego poziomu i tak dalej, aż do document.
inner.addEventListener("click", () => console.log("inner"));
outer.addEventListener("click", () => console.log("outer"));
// Click inner -> logs: "inner" then "outer"Włączanie przechwytywania
Aby nasłuchiwać zamiast tego podczas fazy przechwytywania, należy przekazać trzeci argument o wartości true (lub { capture: true }). Handlery przechwytywania są uruchamiane z góry na dół, przed handlerami propagacji w górę.
outer.addEventListener("click", () => console.log("outer capture"), true);
inner.addEventListener("click", () => console.log("inner bubble"));
// Click inner -> "outer capture" then "inner bubble"Pełna kolejność
Dla kliknięcia elementu #inner z handlerami w obu fazach kolejność jest następująca: faza przechwytywania od góry do dołu, następnie element docelowy, a potem faza propagacji w górę od dołu do góry.
- przechwytywanie na document
- przechwytywanie na outer
- inner (element docelowy)
- propagacja w górę na outer
- propagacja w górę na document
event.target a event.currentTarget
event.target to element, który rzeczywiście wywołał zdarzenie, czyli miejsce kliknięcia. event.currentTarget to element, którego listener jest obecnie wykonywany. W handlerze elementu nadrzędnego obsługującym propagację w górę te wartości są różne.
outer.addEventListener("click", (e) => {
console.log(e.target.id); // "inner" - where click occurred
console.log(e.currentTarget.id); // "outer" - listener owner
});Zatrzymywanie propagacji
event.stopPropagation() zatrzymuje dalszą drogę zdarzenia: nie przejdzie ono do następnego elementu w bieżącej fazie. Handlery elementów nadrzędnych znajdujących się wyżej w drzewie nie zostaną uruchomione.
inner.addEventListener("click", (e) => {
e.stopPropagation();
console.log("handled here only");
});
outer.addEventListener("click", () => console.log("never runs"));stopImmediatePropagation
stopPropagation() nadal pozwala działać innym listenerom na tym samym elemencie. Aby zablokować również sąsiednie listenery na tym elemencie, należy użyć event.stopImmediatePropagation().
inner.addEventListener("click", (e) => {
e.stopImmediatePropagation();
console.log("first only");
});
inner.addEventListener("click", () => console.log("blocked"));preventDefault działa inaczej
Nie należy mylić preventDefault() z stopPropagation(). preventDefault() anuluje domyślną akcję przeglądarki (przejście za odnośnikiem, wysłanie formularza), ale NIE zatrzymuje propagacji zdarzenia w górę.
link.addEventListener("click", (e) => {
e.preventDefault(); // do not navigate
// event still bubbles to parents
});Dlaczego przechwytywanie jest rzadkie
Większość kodu korzysta z propagacji w górę, ponieważ odpowiada to intuicji: najpierw reaguje konkretny element, a następnie informację o zdarzeniu otrzymują kontenery. Przechwytywanie jest przydatne, gdy element nadrzędny musi przechwycić lub odrzucić zdarzenie, zanim zobaczą je elementy potomne.
Sprawdzanie fazy
event.eventPhase informuje, która faza jest aktywna: 1 — przechwytywanie, 2 — cel, 3 — propagacja w górę. Jest to rzadko potrzebne, ale pomaga podczas debugowania złożonych łańcuchów listenerów.
el.addEventListener("click", (e) => {
console.log(e.eventPhase); // 1, 2, or 3
}, true);Nie wszystkie zdarzenia propagują się w górę
Większość zdarzeń interfejsu użytkownika (click, input, keydown) propaguje się w górę. Kilka z nich domyślnie tego nie robi, na przykład focus, blur i mouseenter. W ich przypadku należy użyć wariantów propagujących się w górę (focusin, focusout) albo fazy przechwytywania.
Szybki test
Proszę sprawdzić rozumienie faz zdarzeń.
Podsumowanie
Zdarzenia najpierw przechodzą przez fazę przechwytywania (w dół), a następnie przez fazę propagacji w górę (w górę). Listenery domyślnie korzystają z propagacji w górę; aby włączyć przechwytywanie, należy przekazać true. e.target to źródło zdarzenia, a e.currentTarget to element, do którego należy listener. stopPropagation() zatrzymuje propagację, a preventDefault() anuluje domyślne akcje. Te dwie fazy stanowią podstawę delegowania zdarzeń.
Często zadawane pytania
Czy lekcja „Fazy przechwytywania i propagacji” jest bezpłatna?
Tak — pełny tekst „Fazy przechwytywania i propagacji” jest dostępny za darmo tutaj w sieci. Aby ćwiczyć ją interaktywnie (wbudowany edytor kodu i tutor AI dostępny 24/7) i odblokować resztę kursu JavaScript Academy, przejdź na CoddyKit PRO. Kurs JavaScript Academy zawiera 4 lekcji w sumie.
Co nauczysz się w „Fazy przechwytywania i propagacji”?
Proszę zrozumieć, jak zdarzenia przemieszczają się przez DOM. Ćwiczysz JavaScript Academy z praktycznym kodem, który uruchamiasz bezpośrednio w przeglądarce, a tutor AI dostępny 24/7 odpowiada na Twoje pytania podczas pracy nad lekcją.
Czy potrzebuję doświadczenia, aby zacząć JavaScript Academy?
Nie wymagamy żadnego doświadczenia. JavaScript Academy w CoddyKit jest strukturyzowany dla początkujących i zaawansowanych użytkowników, więc możesz zacząć tutaj lub od początku i uczyć się w swoim tempie. To lekcja 1 z 4.
Ile czasu zajmuje lekcja „Fazy przechwytywania i propagacji”?
Większość lekcji CoddyKit trwa około 5–10 minut. Każda lekcja to mały, interaktywny krok, dzięki czemu robisz systematyczne postępy i zawsze wracasz dokładnie do tego samego miejsca — na webie i w aplikacji.
Czy mogę pisać i uruchamiać kod w tej lekcji JavaScript Academy?
Tak. Każda lekcja JavaScript Academy zawiera wbudowany edytor kodu, więc piszesz i uruchamiasz prawdziwy kod bezpośrednio w przeglądarce i od razu otrzymujesz sprzężenie zwrotne od AI — bez konfiguracji na komputerze.
Wszystkie lekcje w tym kursie
- Fazy przechwytywania i propagacji
- Wzorzec delegowania zdarzeń
- Dynamiczne listy z delegowaniem zdarzeń
- Zdarzenia niestandardowe