Kurs obiektowego JavaScript (33)

Autor: Damian Chodorek • Opublikowany: 4 listopada 2014 • Ostatnia aktualizacja: 8 lutego 2015 • Kategoria: javascript, kursy

Obsługa zdarzeń. Model bąbelkowy.

Czym są zdarzenia? To zajście jakiegoś zjawiska, które zostało zarejestrowane przez przeglądarkę. Przykładowo, zdarzeniem jest:

  • kliknięcie elementu przez użytkownika,
  • wejście na stronę,
  • opuszczenie strony,
  • zmiana rozmiaru przeglądarki,
  • przewinięcie strony w dół.

Wszystkie takie zdarzenia są rejestrowane przez przeglądarkę internetową. Programista JS ma możliwość ich obsłużenia. To znaczy, że przeglądarka wywoła nasz kawałek kodu w momencie zajścia danego wydarzenia. Naszym zadaniem jest poinformowanie przeglądarki, który kawałek kodu ma być wywołany oraz które zdarzenie ma go wywołać.

Atrybuty inline

Metoda obsługiwania zdarzeń, którą zaraz opiszę istnieje, ale powinno się jej unikać. Polega ona na tym, że wstrzykujemy fragment kodu JS do HTML’a. Jak już pisałem wcześniej, to zła praktyka, ponieważ powoduje wymieszanie się dwóch logicznych części (treść – HTML i zachowanie – JS), które powinny być rozdzielone.

Załóżmy, że mamy element div, który reprezentuje na stronie jakiś przycisk. Chcemy przechwycić zdarzenie kliknięcia, a potem na nie zareagować.

<div id="div1" onclick="alert('klik')">kliknij tutaj</div>

Tag onclick zawiera kod, który zostanie wywołany po kliknięciu elementu. Może być to dowolna funkcja. Jest to jednak niepolecana metoda.

Drugi sposób to skorzystanie z pola onclick.

var div=document.getElementById("div1");
div.onclick=function(){
  console.log("klik!");
};

Najlepsza praktyka

Poznane do tej pory sposoby sposoby nie pozawalają na wywołanie wielu funkcji w momencie zajścia zdarzenia, w sposób niezależny od siebie. Umożliwia to jednak metoda addEventListener().

var div=document.getElementById("div1");
div.addEventListener(
  'click',
  function(){ console.log('funkcja 1 działa'); }
);

div.addEventListener(
  'click',
  function(){ console.log('funkcja 2 działa'); }
);

Pierwszym argumentem funkcji jest nazwa zdarzenia, a drugim funkcja, która ma zostać wywołana w momencie jego wystąpienia.

Bąbelkowanie zdarzeń (event bubbling)

Rozważmy hierarchiczną strukturę:

<body>
  <ul>
    <li><a href="#">link do bloga</a></li>
  </ul>
</body>

Zauważ, że kliknięcie na elemencie a oznacza kliknięcie na li, ul oraz body. Dzieje się to na wskutek propagacji zdarzeń. Mogą być dwa sposoby rozpropagowania kliknięcia elementu a:

  • przechwytywanie zdarzeniabody -> ul -> li -> a,
  • bąbelkowanie zdarzeniaa -> li -> ul -> body (pęknięcie wewnętrznego bąbelka powoduje pęknięcie nadrzędnego).

Specyfikacja DOM Level 2 mówi, że powinny nastąpić trzy kolejne fazy: przechwytywanie zdarzenia, element docelowy, bąbelkowanie.

body -> ul -> li -> a
a (element docelowy)
a -> li -> ul -> body (powrót)

Trzeci parametr metody addEventListener() mówi czy powinno odbyć się przechwytywanie. Przeglądarki różnią się jeśli chodzi o implementację tegoż modelu, a więc jeśli chcesz zachować przenośność kodu, powinieneś przekazywać false (odbędzie się wyłącznie bąbelkowanie).

Aby na którymś etapie zatrzymać pękanie bąbelek, możesz skorzystać z metody stopPropagation().

document.body.addEventListener( 'click', function(){ console.log('body'); } );
document.getElementsByTagName('ul')[0].addEventListener( 'click', function(){ console.log('ul'); } );
document.getElementsByTagName('a')[0].addEventListener( 'click', function(){ console.log('a'); } );

liHandler=function(){ console.log('li'); };
document.getElementsByTagName('li')[0].addEventListener( 'click', liHandler );

//po kliknięciu:
//a
//li
//ul
//body 

//usuwamy handler
document.getElementsByTagName('li')[0].removeEventListener( 'click', liHandler );

//po kliknięciu:
//a
//ul
//body 

//zatrzymanie propagacji
document.getElementsByTagName('li')[0].addEventListener( 'click', function(e){ console.log('li'); e.stopPropagation(); } );

//po kliknięciu:
//a
//li

Zauważ, że nie możemy usunąć event listenera, który wywołuje funkcję anonimową.

W tym artykule to wszystko. Przejdź do następnej części:

Kurs obiektowego JavaScript (34)

Zobacz również
Kurs obiektowego JavaScript (31)Wstawianie, usuwanie i zamiana węzłów.
Kurs obiektowego JavaScript (32)Omówienie obiektów skrótowych w JS.
Kurs obiektowego JavaScript (34)Zapobieganie działaniu domyślnemu. Rodzaje zdarzeń.
Kurs obiektowego JavaScript (35)Zapytania do serwera. AJAX oraz XMLHttpRequest.

Dodaj komentarz

Twój adres e-mail nie zostanie opublikowany.