Jaka jest różnica między addEventListener
i onclick
?
var h = document.getElementById("a");
h.onclick = dothing1;
h.addEventListener("click", dothing2);
Powyższy kod znajduje się razem w osobnym pliku .js i oba działają doskonale.
źródło
Jaka jest różnica między addEventListener
i onclick
?
var h = document.getElementById("a");
h.onclick = dothing1;
h.addEventListener("click", dothing2);
Powyższy kod znajduje się razem w osobnym pliku .js i oba działają doskonale.
Oba są poprawne, ale żadne z nich nie jest „najlepsze” per se, i może istnieć powód, dla którego deweloper zdecydował się na oba podejścia.
Detektory zdarzeń (addEventListener i IE's attachEvent)
Wcześniejsze wersje Internet Explorera implementują javascript inaczej niż prawie każda inna przeglądarka. W wersjach mniejszych niż 9 używasz metody attachEvent
[ doc ], jak poniżej:
element.attachEvent('onclick', function() { /* do stuff here*/ });
W większości innych przeglądarek (w tym IE 9 i nowszych) używasz addEventListener
[ doc ], jak poniżej:
element.addEventListener('click', function() { /* do stuff here*/ }, false);
Korzystając z tego podejścia ( zdarzenia DOM Level 2 ), możesz dołączyć teoretycznie nieograniczoną liczbę zdarzeń do dowolnego pojedynczego elementu. Jedynym praktycznym ograniczeniem jest pamięć po stronie klienta i inne problemy z wydajnością, które są różne dla każdej przeglądarki.
Powyższe przykłady przedstawiają użycie anonimowej funkcji [ doc ]. Możesz także dodać detektor zdarzeń, korzystając z odwołania do funkcji [ doc ] lub zamknięcia [ doc ]:
var myFunctionReference = function() { /* do stuff here*/ }
element.attachEvent('onclick', myFunctionReference);
element.addEventListener('click', myFunctionReference , false);
Inną ważną cechą addEventListener
jest parametr końcowy, który kontroluje sposób, w jaki słuchacz reaguje na propagację zdarzeń [ doc ]. W przykładach podawałem fałsz, co jest standardem w prawdopodobnie 95% przypadków użycia. Nie ma równoważnego argumentu attachEvent
ani dla zdarzeń wbudowanych.
Zdarzenia wbudowane (właściwość HTML onclick = "" i element.onclick)
We wszystkich przeglądarkach obsługujących javascript można wstawić detektor zdarzeń bezpośrednio, co oznacza bezpośrednio w kodzie HTML. Prawdopodobnie widziałeś to:
<a id="testing" href="#" onclick="alert('did stuff inline');">Click me</a>
Najbardziej doświadczeni programiści unikają tej metody, ale wykonuje zadanie; to jest proste i bezpośrednie. Nie możesz tutaj używać zamknięć ani anonimowych funkcji (chociaż sam program obsługi jest swego rodzaju anonimową funkcją), a twoja kontrola zakresu jest ograniczona.
Druga metoda, o której wspominasz:
element.onclick = function () { /*do stuff here */ };
... jest odpowiednikiem wbudowanego javascript, z tym wyjątkiem, że masz większą kontrolę nad zakresem (ponieważ piszesz skrypt zamiast HTML) i możesz używać anonimowych funkcji, odwołań do funkcji i / lub zamknięć.
Istotną wadą zdarzeń wbudowanych jest to, że w przeciwieństwie do detektorów zdarzeń opisanych powyżej, można przypisać tylko jedno zdarzenie wbudowane. Zdarzenia wbudowane są przechowywane jako atrybut / właściwość elementu [ doc ], co oznacza, że można je zastąpić.
Korzystając z przykładu <a>
z powyższego kodu HTML:
var element = document.getElementById('testing');
element.onclick = function () { alert('did stuff #1'); };
element.onclick = function () { alert('did stuff #2'); };
... kiedy kliknąłeś element, zobaczysz tylko „Zrobiłem rzeczy # 2” - nadpisałeś pierwszą przypisaną onclick
właściwość drugą wartością, a także nadpisałeś oryginalną wbudowaną onclick
właściwość HTML . Sprawdź to tutaj: http://jsfiddle.net/jpgah/ .
Mówiąc ogólnie, nie używaj zdarzeń wbudowanych . Mogą istnieć konkretne przypadki użycia, ale jeśli nie jesteś w 100% pewien, że masz taki przypadek użycia, nie używasz i nie powinieneś używać zdarzeń wbudowanych.
Nowoczesne Javascript (Angular i tym podobne)
Od czasu opublikowania tej odpowiedzi frameworki javascript, takie jak Angular, stały się znacznie bardziej popularne. Kod taki zobaczysz w szablonie Angular:
<button (click)="doSomething()">Do Something</button>
To wygląda jak zdarzenie wbudowane, ale tak nie jest. Ten typ szablonu zostanie przełożony na bardziej złożony kod, który korzysta z detektorów zdarzeń za sceną. Wszystko, co tu napisałem o wydarzeniach, nadal obowiązuje, ale jesteś usunięty z drobiazgów przez co najmniej jedną warstwę. Powinieneś rozumieć rzeczy, ale jeśli najlepsze praktyki nowoczesnego frameworka JS obejmują pisanie tego rodzaju kodu w szablonie, nie myśl, że używasz zdarzenia wbudowanego - nie jesteś.
Który jest najlepszy?
Pytanie dotyczy kompatybilności i konieczności przeglądarki. Czy chcesz dołączyć więcej niż jedno zdarzenie do elementu? Czy będziesz w przyszłości? Szanse są, będziesz. Konieczne są attachEvent i addEventListener. Jeśli nie, zdarzenie wbudowane może wydawać się, że zrobi to samo, ale lepiej jest przygotować się na przyszłość, która - choć może wydawać się mało prawdopodobna - jest przynajmniej przewidywalna. Istnieje szansa, że będziesz musiał przejść do nasłuchiwania zdarzeń opartych na JS, więc możesz po prostu zacząć od tego. Nie używaj wbudowanych zdarzeń.
jQuery i inne frameworki javascript hermetyzują różne implementacje przeglądarki poziomu DOM 2 zdarzeń w modelach ogólnych, dzięki czemu możesz pisać kod zgodny z różnymi przeglądarkami bez martwienia się o historię IE jako buntownika. Ten sam kod z jQuery, wszystkie przeglądarki i gotowe do działania:
$(element).on('click', function () { /* do stuff */ });
Jednak nie zabraknie i zdobędziesz ramy tylko dla tej jednej rzeczy. Możesz łatwo uruchomić własne małe narzędzie do obsługi starszych przeglądarek:
function addEvent(element, evnt, funct){
if (element.attachEvent)
return element.attachEvent('on'+evnt, funct);
else
return element.addEventListener(evnt, funct, false);
}
// example
addEvent(
document.getElementById('myElement'),
'click',
function () { alert('hi!'); }
);
Wypróbuj: http://jsfiddle.net/bmArj/
Biorąc to wszystko pod uwagę, chyba że skrypt, na który patrzysz, wziąłby pod uwagę różnice w przeglądarce w inny sposób (w kodzie nie pokazanym w pytaniu), użycie części addEventListener
nie działałoby w wersjach IE mniejszych niż 9.
Dokumentacja i powiązane czytanie
function addEvent(element, myEvent, fnc) { return ((element.attachEvent) ? element.attachEvent('on' + myEvent, fnc) : element.addEventListener(myEvent, fnc, false)); }
function addEvent(e,n,f){return e.attachEvent?e.attachEvent('on'+n,f):e.addEventListener(n,f,!!0)}
<< Przy 98 znakach ten jest o ponad 40% mniejszy!Różnica, którą można zobaczyć, gdybyś miał jeszcze kilka funkcji:
Funkcje 2, 3 i 4 działają, ale 1 nie. Wynika to z faktu,
addEventListener
że nie zastępuje istniejących procedur obsługi zdarzeń, aonclick
zastępuje wszelkie istniejąceonclick = fn
procedury obsługi zdarzeń.Inną znaczącą różnicą jest to, że
onclick
zawsze będzie działać, podczasaddEventListener
gdy nie działa w Internet Explorerze przed wersją 9. Możesz użyć analogicznejattachEvent
(która ma nieco inną składnię) w IE <9.źródło
W tej odpowiedzi opiszę trzy metody definiowania programów obsługi zdarzeń DOM.
element.addEventListener()
Przykład kodu:
Pokaż fragment kodu
element.addEventListener()
ma wiele zalet:element.removeEventListener()
.useCapture
parametr, który wskazuje, czy chcesz obsłużyć zdarzenie w fazie przechwytywania czy propagacji . Zobacz: Nie można zrozumieć atrybutu useCapture w addEventListener ..onevent
właściwości elementów DOM, wielu niedoświadczonych programistów JavaScript uważa, że nazwa zdarzenia to na przykładonclick
lubonload
.on
to nie jest częścią nazwy zdarzenia . Prawidłowymi nazwami zdarzeń sąclick
iload
, i tak przekazywane są nazwy zdarzeń.addEventListener()
.element.onevent = function() {}
(na przykładonclick
,onload
)Przykład kodu:
Pokaż fragment kodu
Był to sposób na zarejestrowanie procedur obsługi zdarzeń w DOM 0. Jest to teraz odradzane, ponieważ:
onevent
właściwość do stanu początkowego (tjnull
.).window.onload
, na przykładwindow.onload = "test";
:, nie spowoduje to żadnych błędów. Twój kod nie działałby i naprawdę trudno byłoby dowiedzieć się, dlaczego..addEventListener()
wyrzuciłby jednak błąd (przynajmniej w Firefox): TypeError: Argument 2 EventTarget.addEventListener nie jest obiektem .Wbudowane moduły obsługi zdarzeń (
onevent
atrybut HTML)Przykład kodu:
Pokaż fragment kodu
Podobnie
element.onevent
jak teraz, jest to odradzane. Oprócz problemówelement.onevent
, które:Content-Security-Policy
nagłówek HTTP, aby blokować wbudowane skrypty i zezwalać na skrypty zewnętrzne tylko z zaufanych domen. Zobacz, jak działa Polityka bezpieczeństwa treści?Zobacz też
EventTarget.addEventListener()
dokumentacja (MDN)EventTarget.removeEventListener()
dokumentacja (MDN)źródło
Chociaż
onclick
działa we wszystkich przeglądarkach,addEventListener
nie działa w starszych wersjach programu Internet Explorer, którego używaattachEvent
zamiast tego.Minusem
onclick
jest to, że może istnieć tylko jeden moduł obsługi zdarzeń, a pozostałe dwa będą wyzwalać wszystkie zarejestrowane wywołania zwrotne.źródło
O ile mi wiadomo, zdarzenie „load” DOM nadal działa tylko w bardzo ograniczonym zakresie. Oznacza to, że będzie to tylko na ogień
window object
,images
a<script>
elementy instancji. To samo dotyczy bezpośredniegoonload
zadania. Nie ma technicznej różnicy między tymi dwoma. Prawdopodobnie.onload =
ma lepszą dostępność w różnych przeglądarkach.Jednak nie można przypisać
load event
do<div>
lub<span>
elementu lub etażerka.źródło
Podsumowanie:
addEventListener
można dodawać wiele zdarzeń, przyonclick
czym nie można tego zrobić.onclick
można dodać jakoHTML
atrybut, podczas gdyaddEventListener
można dodać tylko w<script>
elementach.addEventListener
może przyjąć trzeci argument, który może zatrzymać propagację zdarzenia.Oba mogą być używane do obsługi zdarzeń. Jednak
addEventListener
powinien być preferowanym wyborem, ponieważ może zrobić wszystko, coonclick
robi i więcej. Nie używaj wbudowanychonclick
jako atrybutów HTML, ponieważ mieszają one javascript i HTML, co jest złą praktyką. To sprawia, że kod jest mniej konserwowalny.źródło
onclick
przewodników w obawie przed wyśmiewaniem się z pokoju - ale zwykle wydarzenia w ostatnich latach są znacznie gorsze i mniej konserwatywne. Klasy podobajs-link
,js-form-validation
czy dane z atrybutówdata-jspackage="init"
nie jest w żaden sposób lepiej ... A jak ofteen czy rzeczywiście użyć pęcherzyków wydarzenie? Ja osobiście chciałbym móc napisać moduł obsługi bez sprawdzania, czy cel jest w rzeczywistości zgodny z moim elementem - lub konieczności zatrzymania propagacji w kilku miejscach z powodu przypadkowych błędów.Jeszcze jeden szczegół nie został zauważony: współczesne przeglądarki komputerowe uważają różne naciśnięcia przycisków za „kliknięcia”
AddEventListener('click'
ionclick
domyślnie.onclick
iAddEventListener
strzelaj lewym i środkowym kliknięciem.onclick
działa tylko przy kliknięciu lewym przyciskiem, aleAddEventListener
kliknięcie przy lewym, środkowym i prawym kliknięciu.Ponadto zachowanie kliknięcia środkowym przyciskiem jest bardzo niespójne w różnych przeglądarkach, gdy są włączone kursory przewijania:
Warto również zauważyć, że zdarzenia „kliknięcia” dla dowolnego elementu HTML wybieranego za pomocą klawiatury, takiego jak
input
również strzelanie w spację lub wejście po wybraniu tego elementu.źródło
JavaScript zwykle łączy wszystko w obiekty, co może powodować zamieszanie. Wszystko w jednym to sposób JavaScript.
Zasadniczo onclick jest atrybutem HTML. Natomiast addEventListener to metoda na obiekcie DOM reprezentująca element HTML.
W obiektach JavaScript metoda jest jedynie właściwością, która ma funkcję jako wartość i działa przeciwko obiektowi, do którego jest dołączona (na przykład za pomocą tej metody).
W JavaScript jako element HTML reprezentowany przez DOM będzie miał przypisane atrybuty do jego właściwości.
Tutaj ludzie się mylą, ponieważ JavaScript łączy wszystko w jeden kontener lub przestrzeń nazw bez warstwy pośredniej.
W normalnym układzie OO (który przynajmniej łączy przestrzeń nazw właściwości / metod) możesz mieć coś takiego:
Istnieją różne warianty, w których można użyć gettera / settera dla onload lub HashMap dla atrybutów, ale ostatecznie tak to by wyglądało. JavaScript wyeliminował tę warstwę pośrednictwa, spodziewając się wiedzieć, co jest między innymi. Połączył domElement i atrybuty razem.
Z wyjątkiem kompatybilności powinieneś jako najlepszą praktykę użyć addEventListener. Gdy inne odpowiedzi mówią o różnicach w tym względzie, a nie o podstawowych różnicach programowych, zapomnę o tym. Zasadniczo w idealnym świecie, którego naprawdę chcesz używać tylko z * HTML, ale w jeszcze bardziej idealnym świecie nie powinieneś robić czegoś takiego z HTML.
Dlaczego dziś dominuje? Szybsze pisanie, łatwiejsze do nauczenia i zwykle działa.
Głównym celem onload w HTML jest przede wszystkim zapewnienie dostępu do metody lub funkcjonalności addEventListener. Używając go w JS, przechodzisz przez HTML, kiedy możesz zastosować go bezpośrednio.
Hipotetycznie możesz tworzyć własne atrybuty:
To, co robi JS, jest nieco inne.
Możesz to zrównać z czymś takim (dla każdego utworzonego elementu):
Rzeczywiste szczegóły implementacji prawdopodobnie będą się różnić w zależności od szeregu subtelnych odmian, które w niektórych przypadkach będą nieco inne, ale to sedno.
Prawdopodobnie jest to hack kompatybilności, w którym można przypiąć funkcję do atrybutu on, ponieważ domyślnie wszystkie atrybuty są łańcuchami.
źródło
Według MDN różnica jest następująca:
addEventListener:
na kliknięcie:
Istnieje również różnica w składni, jak widać w poniższych kodach:
addEventListener:
na kliknięcie:
źródło
Jeśli nie martwisz się zbytnio obsługą przeglądarki, istnieje sposób na ponowne powiązanie odwołania „this” w funkcji wywoływanej przez zdarzenie. Zwykle wskazuje element, który wygenerował zdarzenie, gdy funkcja jest wykonywana, co nie zawsze jest tym, czego chcesz. Problem polega na tym, aby jednocześnie móc usunąć ten sam detektor zdarzeń, jak pokazano w tym przykładzie: http://jsfiddle.net/roenbaeck/vBYu3/
Powyższy kod działa dobrze w przeglądarce Chrome i prawdopodobnie istnieje pewien błąd w dostosowywaniu „wiązania” do innych przeglądarek.
źródło
Korzystanie z wewnętrznych procedur obsługi jest niezgodne z Polityką bezpieczeństwa treści, więc
addEventListener
podejście jest bardziej bezpieczne z tego punktu widzenia. Oczywiście możesz włączyć wbudowane moduły obsługi,unsafe-inline
ale, jak sama nazwa wskazuje, nie jest to bezpieczne, ponieważ przywraca całe hordy exploitów JavaScript, których CSP zapobiega.źródło
Powinno być także możliwe rozszerzenie nasłuchiwania przez prototypowanie go (jeśli mamy do niego odwołanie i nie jest to anonimowa funkcja) lub wywołanie wywołania „onclick” do biblioteki funkcji (funkcja wywołująca inne funkcje)
lubić
oznacza to, że nigdy nie musimy przerywać wywołania onclick, po prostu zmieniamy funkcję myFunctionList (), aby robić to, co chcemy, ale to pozostawia nam kontrolę nad fazami propagacji / wychwytywania, więc należy tego unikać w nowszych przeglądarkach.
na wypadek, gdyby ktoś znalazł ten wątek w przyszłości ...
źródło
Najwyraźniej robią to samo: nasłuchują zdarzenia kliknięcia i wykonują funkcję zwrotną. Niemniej jednak nie są równoważne. Jeśli kiedykolwiek będziesz musiał wybrać jedną z tych dwóch opcji, może to pomóc w ustaleniu, który z nich jest dla Ciebie najlepszy.
Główna różnica polega na tym, że onclick jest tylko właściwością i podobnie jak wszystkie właściwości obiektu, jeśli napiszesz więcej niż jeden raz, zostanie on nadpisany . Zamiast tego za pomocą addEventListener () możemy po prostu powiązać moduł obsługi zdarzeń z elementem i wywołać go za każdym razem, gdy jest to potrzebne, bez obawy o nadpisanie właściwości. Przykład pokazano tutaj,
Spróbuj: https://jsfiddle.net/fjets5z4/5/
Przede wszystkim kusiło mnie, aby nadal używać onclick, ponieważ jest on krótszy i wygląda na prostszy… a tak naprawdę jest. Ale nie polecam już go używać. To tak jak przy użyciu wbudowanego JavaScript. Używanie czegoś takiego - to wbudowany JavaScript - jest obecnie bardzo odradzane (wbudowany CSS jest również odradzany, ale to inny temat).
Jednak funkcja addEventListener (), mimo że jest standardem, po prostu nie działa w starych przeglądarkach (Internet Explorer poniżej wersji 9), a to kolejna duża różnica. Jeśli potrzebujesz obsługi tych starożytnych przeglądarek, powinieneś podążać drogą kliknięcia. Ale możesz także użyć jQuery (lub jednej z jego alternatyw): w zasadzie upraszcza twoją pracę i zmniejsza różnice między przeglądarkami, dzięki czemu możesz zaoszczędzić dużo czasu.
źródło
addEventListener
pozwala ustawić wiele programów obsługi, ale nie jest obsługiwany w IE8 lub starszej wersji.IE ma
attachEvent
, ale nie jest dokładnie tak samo.źródło
Kontekst, do którego odwołuje się
'this'
słowo kluczowe w JavSript, jest inny.spójrz na następujący kod:
To, co robi, jest naprawdę proste. po kliknięciu przycisku przycisk zostanie automatycznie wyłączony.
Najpierw, gdy spróbujesz podłączyć zdarzenia w ten sposób,
button.onclick = function(),
zdarzenie onclick zostanie uruchomione przez kliknięcie przycisku, jednak przycisk nie zostanie wyłączony, ponieważ nie ma wyraźnego powiązania między button.onclick a modułem obsługi zdarzeń onclick. Jeśli debugujesz, zobaczysz'this'
obiekt, możesz zobaczyć, że odnosi się on do'window'
obiektu.Po drugie, jeśli komentujesz
btnSubmit.onclick = disable();
i odkomentujesz//btnSubmit.addEventListener('click', disable, false);
, możesz zobaczyć, że przycisk jest wyłączony, ponieważ w ten sposób istnieje wyraźne powiązanie między zdarzeniem button.onclick a modułem obsługi zdarzeń onclick. Jeśli debugujesz w celu wyłączenia funkcji, zobaczysz, że'this'
odnosi siębutton control
raczej do niżwindow
.Jest to coś, co nie podoba mi się w JavaScript, co jest niespójnością. Btw, jeśli używasz jQuery (
$('#btnSubmit').on('click', disable);
), używa jawnego wiązania.źródło
btnSubmit.onclick = disable;
(przypisać funkcję, a nie wywoływać). W obu przypadkachthis
będzie się odnosić do elementu przycisku.onclick to w zasadzie addEventListener, który w szczególności wykonuje funkcję po kliknięciu elementu. Przydatne, gdy masz przycisk, który wykonuje proste operacje, takie jak przycisk kalkulatora. addEventlistener może być używany do wielu rzeczy, takich jak wykonywanie operacji po załadowaniu DOM lub całej zawartości, podobnie jak window.onload, ale z większą kontrolą.
Uwaga: Możesz użyć więcej niż jednego zdarzenia z wbudowanym lub przynajmniej za pomocą onclick, oddzielając każdą funkcję średnikiem, tak jak to ...
Nie napisałbym funkcji z wbudowanym, ponieważ potencjalnie możesz mieć później problemy i byłoby to niechlujne imo. Wystarczy użyć go do wywołania funkcji już wykonanych w pliku skryptu.
Który z nich użyjesz, zależy od tego, czego chcesz. addEventListener do złożonych operacji i onclick dla prostych. Widziałem, że niektóre projekty nie dołączały określonego elementu do elementów i zamiast tego wdrażałyby bardziej globalny program do listy zdarzeń, który określałby, czy stuknięcie w przycisk i wykonuje określone zadania w zależności od tego, co zostało naciśnięte. Imo, które mogłoby potencjalnie prowadzić do problemów, które - jak sądzę - byłyby marnotrawstwem zasobów, gdyby ten słuchacz zdarzeń musiał obsługiwać każde kliknięcie
źródło