addEventListener vs onclick

Qual è la differenza tra addEventListener e onclick ?

 var h = document.getElementById("a"); h.onclick = dothing1; h.addEventListener("click", dothing2); 

Il codice sopra risiede insieme in un file .js separato, ed entrambi funzionano perfettamente.

Entrambi sono corretti, ma nessuno di questi è “migliore” di per sé, e potrebbe esserci una ragione per cui lo sviluppatore ha scelto di utilizzare entrambi gli approcci.

Listener di eventi (addEventListener e attachEvent di IE)

Le versioni precedenti di Internet Explorer implementano javascript in modo diverso da quasi tutti gli altri browser. Con versioni inferiori a 9, si utilizza il metodo attachEvent [ doc ], come questo:

 element.attachEvent('onclick', function() { /* do stuff here*/ }); 

Nella maggior parte degli altri browser (incluso IE 9 e versioni successive), si utilizza addEventListener [ doc ], in questo modo:

 element.addEventListener('click', function() { /* do stuff here*/ }, false); 

Utilizzando questo approccio ( eventi di livello 2 DOM ), è ansible associare un numero teoricamente illimitato di eventi a qualsiasi singolo elemento. L’unica limitazione pratica è la memoria lato client e altri problemi di prestazioni, diversi per ogni browser.

Gli esempi sopra rappresentano l’utilizzo di una funzione anonima [ doc ]. Puoi anche aggiungere un listener di eventi utilizzando un riferimento funzione [ doc ] o una chiusura [ doc ]:

 var myFunctionReference = function() { /* do stuff here*/ } element.attachEvent('onclick', myFunctionReference); element.addEventListener('click', myFunctionReference , false); 

Un’altra importante caratteristica di addEventListener è il parametro finale, che controlla il modo in cui il listener reagisce agli eventi di bubbling [ doc ]. Ho passato false negli esempi, che è standard per il 95% dei casi d’uso. Non esiste un argomento equivalente per attachEvent o quando si utilizzano eventi inline.

Eventi in linea (HTML onclick = “” property ed element.onclick)

In tutti i browser che supportano javascript, puoi inserire un listener di eventi in linea, ovvero nel codice HTML. Probabilmente hai visto questo:

 Click me 

Gli sviluppatori più esperti non rispettano questo metodo, ma svolgono il lavoro; è semplice e diretto. Non è ansible utilizzare le chiusure o le funzioni anonime qui (sebbene il gestore stesso sia una sorta di funzione anonima) e il controllo dell’ambito è limitato.

L’altro metodo che menzioni:

 element.onclick = function () { /*do stuff here */ }; 

… è l’equivalente di inline javascript eccetto il fatto che si ha un maggiore controllo dell’ambito (dal momento che si sta scrivendo uno script piuttosto che HTML) e si possono usare funzioni anonime, riferimenti alle funzioni e / o chiusure.

Lo svantaggio significativo degli eventi in linea è che, a differenza degli ascoltatori di eventi descritti sopra, è ansible assegnare un solo evento in linea. Gli eventi in linea sono memorizzati come attributo / proprietà dell’elemento [ doc ], il che significa che può essere sovrascritto.

Utilizzando l’esempio dall’HTML sopra:

 var element = document.getElementById('testing'); element.onclick = function () { alert('did stuff #1'); }; element.onclick = function () { alert('did stuff #2'); }; 

… quando hai fatto clic sull’elemento, vedresti solo “Ha aggiunto # 2” – hai sovrascritto il primo assegnato della proprietà onclick con il secondo valore e hai sovrascritto anche la proprietà onclick HTML in linea originale. Dai un’occhiata qui: http://jsfiddle.net/jpgah/ .

Qual è il migliore?

La domanda è una questione di compatibilità e necessità del browser. Al momento è necessario albind più di un evento a un elemento? Lo farai in futuro? Le probabilità sono, lo farai. attachEvent e addEventListener sono necessari. In caso contrario, un evento in linea farà il trucco.

jQuery e altri framework javascript incapsulano le diverse implementazioni del browser degli eventi di livello 2 di DOM in modelli generici in modo da poter scrivere codice compatibile cross-browser senza doversi preoccupare della storia di IE come ribelle. Stesso codice con jQuery, tutto cross-browser e pronto per il rock:

 $(element).on('click', function () { /* do stuff */ }); 

Non correre e ottenere un quadro solo per questa cosa, però. Puoi facilmente eseguire la tua piccola utility per occuparti dei browser più vecchi:

 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!'); } ); 

Provalo: http://jsfiddle.net/bmArj/

Prendendo in considerazione tutto ciò, a meno che lo script che si sta osservando non tenesse conto delle differenze del browser in un altro modo (nel codice non mostrato nella domanda), la parte che utilizza addEventListener non avrebbe funzionato nelle versioni di IE meno di 9.

Documentazione e lettura correlata

  • Specifica HTML W3, attributi Event Handler
  • element.addEventListener su MDN
  • element.attachEvent su MSDN
  • Jquery.on
  • blog di quirksmode “Introduzione agli eventi”
  • Librerie javascript ospitate da CDN su Google

La differenza che potresti vedere se avessi un altro paio di funzioni:

 var h = document.getElementById('a'); h.onclick = doThing_1; h.onclick = doThing_2; h.addEventListener('click', doThing_3); h.addEventListener('click', doThing_4); 

Le funzioni 2, 3 e 4 funzionano, ma 1 no. Questo perché addEventListener non sovrascrive i gestori di eventi esistenti, mentre onclick sovrascrive eventuali gestori di eventi onclick = fn esistenti.

L’altra differenza significativa, ovviamente, è che onclick funzionerà sempre, mentre addEventListener non funziona in Internet Explorer prima della versione 9. È ansible utilizzare l’analogo attachEvent (che ha una syntax leggermente diversa) in IE <9.

In questa risposta descriverò i tre metodi di definizione dei gestori di eventi DOM.

element.addEventListener()

Esempio di codice:

 const element = document.querySelector('a'); element.addEventListener('click', event => event.preventDefault(), true); 
 Try clicking this link. 

Mentre onclick funziona in tutti i browser, addEventListener non funziona nelle versioni precedenti di Internet Explorer, che utilizza invece attachEvent .

Lo svantaggio di onclick è che può esistere un solo gestore di eventi, mentre gli altri due generano tutte le richiamate registrate.

Per quanto ne so, l’evento “load” DOM ​​continua a funzionare solo in modo molto limitato. Ciò significa che verrà triggersto solo per l’ window object , le images e gli elementi , ad esempio. Lo stesso vale per l'assegnazione diretta del carico. Non c'è differenza tecnica tra questi due. Probabilmente. .onload = ha una migliore disponibilità del cross-browser.

Tuttavia, non è ansible assegnare un load event a un elemento

o o whatnot.

Se non sei troppo preoccupato per il supporto del browser, c’è un modo per rebind il riferimento “this” nella funzione chiamata dall’evento. Normalmente punta all’elemento che ha generato l’evento quando viene eseguita la funzione, che non è sempre quello che vuoi. La parte difficile è allo stesso tempo essere in grado di rimuovere lo stesso listener di eventi, come mostrato in questo esempio: http://jsfiddle.net/roenbaeck/vBYu3/

 /* Testing that the function returned from bind is rereferenceable, such that it can be added and removed as an event listener. */ function MyImportantCalloutToYou(message, otherMessage) { // the following is necessary as calling bind again does // not return the same function, so instead we replace the // original function with the one bound to this instance this.swap = this.swap.bind(this); this.element = document.createElement('div'); this.element.addEventListener('click', this.swap, false); document.body.appendChild(this.element); } MyImportantCalloutToYou.prototype = { element: null, swap: function() { // now this function can be properly removed this.element.removeEventListener('click', this.swap, false); } } 

Il codice sopra funziona bene in Chrome, e probabilmente ci sono alcuni shim in giro che rendono il “bind” compatibile con altri browser.

L’utilizzo di gestori in linea non è compatibile con il criterio di sicurezza del contenuto, pertanto l’approccio addEventListener è più sicuro da questo punto di vista. Ovviamente è ansible abilitare i gestori in linea con inline unsafe-inline ma, come suggerisce il nome, non è sicuro poiché riporta tutte le orde di exploit JavaScript che CSP impedisce.

Un dettaglio non è stato ancora notato: i moderni browser desktop considerano le diverse pressioni dei pulsanti come “clic” per AddEventListener('click' e onclick per impostazione predefinita.

  • Su Chrome 42 e IE11, sia onclick che AddEventListener clic sul pulsante sinistro e medio.
  • Su Firefox 38, onclick si triggers solo con il clic sinistro, ma AddEventListener clic AddEventListener clic sinistro, medio e destro.

Inoltre, il comportamento del tasto centrale è molto incoerente tra i browser quando sono coinvolti cursori di scorrimento:

  • Su Firefox, gli eventi del middle click si triggersno sempre.
  • Su Chrome, non si triggersno se il middleclick apre o chiude un cursore di scorrimento.
  • Su IE, si triggersno quando il cursore di scorrimento si chiude, ma non quando si apre.

Vale anche la pena notare che gli eventi di “clic” per qualsiasi elemento HTML selezionabile da tastiera, come l’ input si input anche nello spazio o entrano quando l’elemento è selezionato.

Dovrebbe anche essere ansible estendere l’ascoltatore con la sua prototipazione (se abbiamo un riferimento ad esso e non è una funzione anonima) -oppure fare “onclick” chiama una chiamata a una libreria di funzioni (una funzione che chiama altre funzioni)

piace

  elm.onclick = myFunctionList function myFunctionList(){ myFunc1(); myFunc2(); } 

questo significa che non dobbiamo mai pagare la chiamata onclick, basta modificare la funzione myFunctionList () per fare ciò che vogliamo, ma questo ci lascia senza controllo delle fasi di bubbling / catching, quindi dovrebbe essere evitato per i nuovi browser.

nel caso qualcuno trovi questa discussione in futuro …

Secondo MDN , la differenza è la seguente:

addEventListener:

Il metodo EventTarget.addEventListener () aggiunge l’object compatibile EventListener specificato all’elenco dei listener di eventi per il tipo di evento specificato sul EventTarget su cui è chiamato. L’objective dell’evento può essere un Elemento in un documento, il Documento stesso, una Finestra o qualsiasi altro object che supporti eventi (come XMLHttpRequest).

al clic:

La proprietà onclick restituisce il codice del gestore eventi click sull’elemento corrente. Quando si utilizza l’evento click per triggersre un’azione, considerare anche l’aggiunta della stessa azione all’evento keydown, per consentire l’uso della stessa azione da parte di persone che non utilizzano un mouse o uno schermo tattile. Sintassi element.onclick = functionRef; dove functionRef è una funzione – spesso un nome di una funzione dichiarata altrove o un’espressione di funzione. Vedi “Guida JavaScript: Funzioni” per i dettagli.

C’è anche una differenza di syntax in uso come puoi vedere nei seguenti codici:

addEventListener:

 // Function to change the content of t2 function modifyText() { var t2 = document.getElementById("t2"); if (t2.firstChild.nodeValue == "three") { t2.firstChild.nodeValue = "two"; } else { t2.firstChild.nodeValue = "three"; } } // add event listener to table var el = document.getElementById("outside"); el.addEventListener("click", modifyText, false); 

al clic:

 function initElement() { var p = document.getElementById("foo"); // NOTE: showAlert(); or showAlert(param); will NOT work here. // Must be a reference to a function name, not a function call. p.onclick = showAlert; }; function showAlert(event) { alert("onclick Event detected!"); } 

addEventListener consente di impostare più gestori, ma non è supportato in IE8 o inferiore.

IE ha attachEvent , ma non è esattamente lo stesso.

Javascript tende a fondere tutto in oggetti e questo può renderlo confuso. Tutto in uno è il modo in cui JavaScript.

In sostanza onclick è un attributo HTML. Viceversa addEventListener è un metodo sull’object DOM che rappresenta un elemento HTML.

Negli oggetti JavaScript, un metodo è semplicemente una proprietà che ha una funzione come valore e che funziona contro l’object a cui è collegato (usando questo per esempio).

In JavaScript, l’elemento HTML rappresentato da DOM avrà i suoi attributi associati alle sue proprietà.

È qui che le persone si confondono perché JavaScript fonde tutto in un unico contenitore o spazio dei nomi senza alcun livello di riferimento indiretto.

In un normale layout OO (che almeno unifica lo spazio dei nomi di proprietà / metodi) si potrebbe avere qualcosa di simile:

 domElement.addEventListener // Object(Method) domElement.attributes.onload // Object(Property(Object(Property(String)))) 

Ci sono variazioni come potrebbe usare un getter / setter per onload o HashMap per gli attributi ma alla fine è così che sembrerebbe. JavaScript ha eliminato quel livello di riferimento indiretto all’aspettarsi di sapere cosa c’è tra le altre cose. Ha fuso insieme domElement e attributi.

Escludendo la compatibilità, dovresti utilizzare addEventListener come procedura ottimale. Mentre altre risposte parlano delle differenze in questo senso piuttosto che delle differenze programmatiche fondamentali, la rinuncerò. Essenzialmente, in un mondo ideale che si intende utilizzare esclusivamente su * da HTML, ma in un mondo ancora più ideale non si dovrebbe fare nulla di simile in HTML.

Perché è dominante oggi? È più veloce da scrivere, più facile da imparare e tende a funzionare.

L’intero punto di onload in HTML è di dare accesso al metodo addEventListener o alla funzionalità in primo luogo. Usandolo in JS stai passando attraverso HTML quando potresti applicarlo direttamente.

Ipoteticamente puoi creare i tuoi attributi:

 $('[myclick]').each(function(i, v) { v.addEventListener('click', function() { eval(v.myclick); // eval($(v).attr('myclick')); }); }); 

Ciò che JS fa è un po ‘diverso da quello.

Puoi equipararlo a qualcosa di simile (per ogni elemento creato):

 element.addEventListener('click', function() { switch(typeof element.onclick) { case 'string':eval(element.onclick);break; case 'function':element.onclick();break; } }); 

I dettagli effettivi di implementazione probabilmente differiranno da una serie di sottili variazioni che rendono i due leggermente diversi in alcuni casi, ma questo è il succo di ciò.

È probabilmente un trucco di compatibilità che è ansible attribuire una funzione a un attributo on poiché gli attributi predefiniti sono tutte stringhe.

Sommario:

  1. addEventListener può aggiungere più eventi, mentre con onclick questo non può essere fatto.
  2. onclick può essere aggiunto come attributo HTML , mentre un addEventListener può essere aggiunto solo all’interno degli elementi .
  3. addEventListener può prendere un terzo argomento che può fermare la propagazione dell'evento.

Entrambi possono essere utilizzati per gestire eventi. Tuttavia, addEventListener dovrebbe essere la scelta preferita poiché può fare tutto ciò che onclick fa e altro. Non utilizzare onclick linea come attributi HTML poiché questo mescola il javascript e l'HTML, che è una ctriggers pratica. Rende il codice meno mantenibile.

Il contesto a cui fa riferimento 'this' parola chiave 'this' in JavasSript è diverso.

guarda il seguente codice:

 < !DOCTYPE html>          

Quello che fa è davvero semplice. quando fai clic sul pulsante, il pulsante verrà disabilitato automaticamente.

Per prima cosa quando provi ad agganciare gli eventi in questo modo button.onclick = function(), evento onclick verrà triggersto facendo clic sul pulsante, tuttavia, il pulsante non verrà disabilitato perché non c’è alcun binding esplicito tra button.onclick e onclick event handler. Se esegui il debug, vedi l’object 'this' , puoi vedere che si riferisce all’object 'window' .

In secondo luogo, se si commenta btnSubmit.onclick = disable(); e non commentare //btnSubmit.addEventListener('click', disable, false); puoi vedere che il pulsante è disabilitato perché in questo modo c’è un legame esplicito tra l’evento button.onclick e il gestore eventi onclick. Se esegui il debug nella funzione di disabilitazione, puoi vedere che 'this' riferisce al button control piuttosto che alla window .

Questo è qualcosa che non mi piace di JavaScript che è incoerenza. A proposito, se si utilizza jQuery ( $('#btnSubmit').on('click', disable); ), usa il binding esplicito.