Jak działa multiple addEventListener w JavaScript?

W dokumencie są 2 Skrypty

// my_script.js goes first
document.onclick = function() {
    alert("document clicked");
};

// other_script.js comes after
// this overrides the onclick of my script,
// and alert will NOT be fired
document.onclick = function() {
    return false;
};

Aby upewnić się, że moje Zdarzenie click nie zostanie nadpisane przez inny skrypt, przełączyłem na addEventListener.

// my_script.js goes first
document.addEventListener("click", function() {
    alert("document clicked");
}, false);

// other_script.js comes after
document.addEventListener("click", function() {
    return false;
}, false);
Teraz mam inne pytanie. Skoro return false w drugim kodzie jest zdefiniowany po alert, to dlaczego nie zapobiega wywołaniu alertu?

Co zrobić, jeśli chcę, aby mój skrypt miał pełną kontrolę nad zdarzeniem kliknięcia (jak zwracanie false przez cały czas bez uwzględnienia zdarzeń zdefiniowanych w innych skryptach)?

Author: user1643156, 2013-04-29

1 answers

Co zrobić, jeśli chcę, aby mój skrypt miał pełną kontrolę nad zdarzeniem kliknięcia (jak zwracanie false przez cały czas bez uwzględnienia zdarzeń zdefiniowanych w innych skryptach)?

Jeśli możesz najpierw zarejestrować swój handler, zanim on to zrobi, możesz to zrobić, pod warunkiem, że używana przeglądarka poprawnie implementuje zdarzenia DOM3(co prawdopodobnie robi, chyba że jest to IE8 lub wcześniejszy).

Są tu (co najmniej) cztery rzeczy:

  1. Zapobieganie default.

  2. Zatrzymanie propagacji do elementów nadrzędnych.

  3. Blokowanie wywoływania innych funkcji obsługi tego samego elementu .

  4. Kolejność, w jakiej są powoływani handlerzy.

W kolejności:

1. Zapobieganie domyślnemu

To właśnie robi return false z obsługi DOM0. (Szczegóły: the Story on Return False.) Odpowiednikiem w DOM2 i DOM3 jest preventDefault:

document.addEventListener("click", function(e) {
    e.preventDefault();
}, false);

Zapobieganie domyślnemu może nie być tak istotne dla tego, co robisz, ale ponieważ używałeś return false w swoim handlerze dom0, a to zapobiega domyślnemu, włączam go tutaj dla kompletności.

2. Zatrzymywanie propagacji do elementów przodków

Opiekunowie DOM0 nie mają jak tego zrobić. Dom2 one do, via stopPropagation:

document.addEventListener("click", function(e) {
    e.stopPropagation();
}, false);

Ale stopPropagation nie powstrzymuje wywoływania innych obsługi tego samego elementu. Od spec :

Metoda stopPropagation zapobiega dalszemu rozprzestrzenianiu się zdarzenia podczas przepływu zdarzeń. Jeśli ta metoda zostanie wywołana przez jakąkolwiek EventListener, Zdarzenie przestanie rozprzestrzeniać się przez drzewo. Zdarzenie zakończy wysyłanie do wszystkich słuchaczy na bieżącym EventTarget przed zatrzymaniem przepływu zdarzenia.

(mój nacisk.)

3. W przeciwieństwie do innych elementów, które nie są wywołane przez element , element nie jest wywoływany przez element

Naturalnie, to nie wyszło dla DOM0, ponieważ nie mogą być inne procedury obsługi tego samego Zdarzenia na tym samym elemencie. :-)

Z tego co wiem, w DOM2 nie da się tego zrobić, ale DOM3 daje nam stopImmediatePropagation:

document.addEventListener("click", function(e) {
    e.stopImmediatePropagation();
}, false);

Niektóre biblioteki oferują tę funkcję (nawet w systemach innych niż DOM3, takich jak IE8) dla programów obsługi podłączonych przez Bibliotekę, patrz poniżej.

4. Kolejność, w jakiej nazywa się osoby obsługujące

Znowu nie coś co ma związek z DOM0, bo nie mogło być innego pomocnicy.

W DOM2, Specyfikacja jawnie mówi, że kolejność wywoływania programów obsługi dołączonych do elementu nie jest gwarantowana; ale DOM3 zmienia to, mówiąc, że programy obsługi są wywoływane w kolejności, w jakiej zostały zarejestrowane.

Najpierw z sekcji DOM2 1.2.1:

Chociaż wszystkie EventListeners na EventTarget są gwarantowane, że zostaną wywołane przez każde zdarzenie, które zostanie odebrane przez to EventTarget, Nie podano specyfikacji co do zamówienia w którym otrzymają wydarzenie w odniesieniu do drugiego {[12] } na EventTarget.

Ale to jest zastępowane przez sekcję DOM3 3.1:

Następnie implementacja musi określić słuchaczy zdarzeń kandydata danego celu. To musi być lista wszystkich słuchaczy zdarzeń, które zostały zarejestrowane na bieżącym celu w kolejności rejestracji .

(mój nacisk.)

Niektóre biblioteki gwarantują zamówienie, pod warunkiem podłączenia wydarzeń do biblioteki.

Warto również zauważyć, że w poprzedniku Microsoftu do DOM2 (np. attachEvent), było to przeciwieństwo kolejności DOM3: obsługa była wywoływana w odwrotnej kolejności rejestracji.


Więc biorąc #3 i # 4 razem, jeśli możesz najpierw zarejestrować swój handler, zostanie on wywołany jako pierwszy i możesz użyć stopImmediatePropagation, aby zapobiec wywoływaniu innych handlerów. Pod warunkiem, że przeglądarka implementuje DOM3 prawidłowo.


To wszystko (w tym fakt, że IE8 i wcześniejsze nie implementują nawet zdarzeń DOM2, a tym bardziej DOM3) jest jednym z powodów, dla których ludzie używają bibliotek takich jak jQuery, z których niektóre gwarantują porządek (o ile wszystko podłącza się do ich programów obsługi za pośrednictwem danej biblioteki) i oferują sposoby na powstrzymanie wywoływania nawet innych programów obsługi tego samego elementu. (Na przykład w jQuery kolejność jest kolejnością, w jakiej zostały dołączone, i możesz użyć stopImmediatePropagation, aby zatrzymać połączenia do innych opiekunów. Ale nie próbuję sprzedawać jQuery tutaj, po prostu wyjaśniając, że niektóre libs oferują więcej funkcjonalności niż podstawowe rzeczy DOM.)

 46
Author: T.J. Crowder,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-04-29 08:31:30