es6 change javascript onclick addeventlistener

change - javascript addeventlistener events



addEventListener vs onclick (14)

Resumen:

  1. addEventListener puede agregar múltiples eventos, mientras que con un onclick no se puede hacer.
  2. onclick se puede agregar como un atributo HTML , mientras que un addEventListener solo se puede agregar dentro de los elementos <script> .
  3. addEventListener puede tomar un tercer argumento que puede detener la propagación del evento.

Ambos pueden ser utilizados para manejar eventos. Sin embargo, addEventListener debería ser la opción preferida, ya que puede hacer todo lo que haga con un onclick y más. No use onclick línea como atributos HTML ya que esto mezcla el javascript y el HTML, lo cual es una mala práctica. Hace que el código sea menos mantenible.

¿Cuál es la diferencia entre addEventListener y onclick ?

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

El código anterior reside junto en un archivo .js separado, y ambos funcionan perfectamente.


Aún no se ha observado un detalle: los navegadores de escritorio modernos consideran que las pulsaciones de diferentes botones son "clics" para AddEventListener(''click'' y onclick de forma predeterminada.

  • En Chrome 42 e IE11, tanto onclick como AddEventListener haga clic en disparar al hacer clic izquierdo y medio.
  • En Firefox 38, onclick dispara solo con el clic izquierdo, pero AddEventListener clic se dispara con los clics izquierdo, medio y derecho.

Además, el comportamiento del clic del medio es muy incoherente en todos los navegadores cuando están involucrados los cursores de desplazamiento:

  • En Firefox, los eventos de clic medio siempre se activan.
  • En Chrome, no se activarán si el botón central abre o cierra un cursor de desplazamiento.
  • En IE, se disparan cuando se cierra el cursor de desplazamiento, pero no cuando se abre.

También vale la pena señalar que los eventos de "clic" para cualquier elemento HTML seleccionable por teclado, como la input también se activan en el espacio o se ingresan cuando se selecciona el elemento.


Ambos son correctos, pero ninguno de ellos es "el mejor" per se, y puede haber una razón por la cual el desarrollador eligió usar ambos enfoques.

Oyentes de eventos (addEventListener y attachEvent de IE)

Las versiones anteriores de Internet Explorer implementan javascript de forma diferente a casi cualquier otro navegador. Con versiones menores de 9, utiliza el attachEvent [ doc ], como este:

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

En la mayoría de los otros navegadores (incluidos IE 9 y superiores), usa addEventListener [ doc ], como esto:

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

Usando este enfoque ( eventos de DOM Nivel 2 ), puede adjuntar un número teóricamente ilimitado de eventos a cualquier elemento individual. La única limitación práctica es la memoria del lado del cliente y otros problemas de rendimiento, que son diferentes para cada navegador.

Los ejemplos anteriores representan el uso de una función anónima [ doc ]. También puede agregar un detector de eventos usando una referencia de función [ doc ] o un cierre [ doc ]:

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

Otra característica importante de addEventListener es el parámetro final, que controla cómo reacciona el oyente ante los eventos de propagación [ doc ]. He estado pasando falso en los ejemplos, lo cual es estándar para probablemente el 95% de los casos de uso. No hay un argumento equivalente para attachEvent , o cuando se usan eventos en línea.

Eventos en línea (HTML onclick = "" property y element.onclick)

En todos los navegadores que admiten javascript, puede colocar un detector de eventos en línea, es decir, directamente en el código HTML. Probablemente has visto esto:

<a id="testing" href="#" onclick="alert(''did stuff inline'');">Click me</a>

Los desarrolladores más experimentados evitan este método, pero hace el trabajo; Es simple y directo. No puede usar cierres ni funciones anónimas aquí (aunque el manejador en sí mismo es una función anónima de orden), y su control de alcance es limitado.

El otro método que mencionas:

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

... es el equivalente de javascript en línea, excepto que tiene más control del alcance (ya que está escribiendo un script en lugar de HTML) y puede usar funciones anónimas, referencias de funciones y / o cierres.

El inconveniente importante de los eventos en línea es que, a diferencia de los escuchas de eventos descritos anteriormente, es posible que solo tenga un evento en línea asignado. Los eventos en línea se almacenan como un atributo / propiedad del elemento [ doc ], lo que significa que se puede sobrescribir.

Usando el ejemplo <a> del HTML anterior:

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

... cuando hizo clic en el elemento, solo vería "Did stuff # 2": sobrescribió la primera asignación de la propiedad onclick con el segundo valor y sobrescribió la propiedad onclick HTML original en línea. Compruébelo aquí: http://jsfiddle.net/jpgah/ .

¿Cuál es el mejor?

La cuestión es una cuestión de compatibilidad y necesidad del navegador. ¿Necesita actualmente adjuntar más de un evento a un elemento? ¿Lo harás en el futuro? Las probabilidades son, lo harás. attachEvent y addEventListener son necesarios. Si no, un evento en línea hará el truco.

jQuery y otros marcos de trabajo de javascript encapsulan las diferentes implementaciones de navegador de eventos DOM nivel 2 en modelos genéricos para que pueda escribir código compatible con varios navegadores sin tener que preocuparse por la historia de IE como rebelde. El mismo código con jQuery, todo el navegador cruzado y listo para rockear:

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

Sin embargo, no te quedes sin un marco para esta única cosa. Puedes rodar fácilmente tu propia pequeña utilidad para cuidar de los navegadores más antiguos:

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

Pruébalo: http://jsfiddle.net/bmArj/

Tomando todo eso en consideración, a menos que el script que está viendo tenga en cuenta las diferencias del navegador de alguna otra manera (en el código que no se muestra en su pregunta), la parte que utiliza addEventListener no funcionará en versiones de IE inferiores a 9.

Documentación y lectura relacionada


El contexto al que hace referencia ''this'' palabra clave ''this'' en JavasSript es diferente.

mira el siguiente código:

<!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <title></title> </head> <body> <input id="btnSubmit" type="button" value="Submit" /> <script> function disable() { this.disabled = true; } var btnSubmit = document.getElementById(''btnSubmit''); btnSubmit.onclick = disable(); //btnSubmit.addEventListener(''click'', disable, false); </script> </body> </html>

Lo que hace es realmente simple. Al hacer clic en el botón, el botón se desactivará automáticamente.

Primero, cuando intenta conectar los eventos de esta manera button.onclick = function(), evento onclick se activará al hacer clic en el botón, sin embargo, el botón no se desactivará porque no hay una vinculación explícita entre button.onclick y onclick event entrenador de animales. Si depura ver el objeto ''this'' , puede ver que se refiere al objeto ''window'' .

En segundo lugar, si comenta btnSubmit.onclick = disable(); y //btnSubmit.addEventListener(''click'', disable, false); puede ver que el botón está deshabilitado porque de esta manera hay un enlace explícito entre el evento button.onclick y el controlador de eventos onclick. Si realiza una depuración en la función de inhabilitación, puede ver que ''this'' refiere al button control lugar de a la window .

Esto es algo que no me gusta de JavaScript, que es la inconsistencia. Por cierto, si está utilizando jQuery ( $(''#btnSubmit'').on(''click'', disable); ), utiliza un enlace explícito.


El uso de controladores en línea es incompatible con la Política de seguridad de contenido, por lo que el enfoque addEventListener es más seguro desde ese punto de vista. Por supuesto, puede habilitar los manejadores en línea con unsafe-inline pero, como su nombre indica, no es seguro ya que trae todas las hordas de vulnerabilidades de JavaScript que CSP impide.


En esta respuesta, describiré los tres métodos para definir los controladores de eventos DOM.

element.addEventListener()

Ejemplo de código:

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

<a href="//google.com">Try clicking this link.</a>

element.addEventListener() tiene múltiples ventajas:

  • Le permite registrar manejadores de eventos ilimitados y eliminarlos con element.removeEventListener() .
  • Tiene el parámetro useCapture , que indica si desea manejar el evento en su fase de captura o propagación . Consulte: No se puede entender el atributo useCapture en addEventListener .
  • Se preocupa por la semántica . Básicamente, hace que el registro de los controladores de eventos sea más explícito. Para un principiante, una llamada a la función hace que sea obvio que algo sucede , mientras que la asignación de eventos a alguna propiedad del elemento DOM es al menos no intuitiva.
  • Le permite separar la estructura del documento (HTML) y la lógica (JavaScript) . En pequeñas aplicaciones web puede parecer que no importa, pero importa con cualquier proyecto más grande. Es mucho más fácil mantener un proyecto que separa la estructura y la lógica que un proyecto que no lo hace.
  • Elimina la confusión con nombres de eventos correctos. Debido al uso de escuchas de eventos en línea o la asignación de escuchas de eventos a .onevent propiedades .onevent de los elementos DOM, muchos programadores de JavaScript inexpertos piensan que el nombre del evento es, por ejemplo, onclick o onload . on no es parte del nombre del evento . Los nombres de eventos correctos son click y load , y así es como se pasan los nombres de eventos a .addEventListener() .
  • Funciona en casi todos los navegadores . Si todavía tiene que admitir IE <= 8, puede usar un polyfill de MDN .

element.onevent = function() {} (por ejemplo, onclick , onload )

Ejemplo de código:

const element = document.querySelector(''a''); element.onclick = event => event.preventDefault();

<a href="//google.com">Try clicking this link.</a>

Esta fue una forma de registrar controladores de eventos en DOM 0. Ahora está desanimado, porque:

  • Le permite registrar un solo controlador de eventos. Asimismo, la eliminación del controlador asignado no es intuitiva, ya que para eliminar el controlador de eventos asignado mediante este método, debe revertir la propiedad del onevent a su estado inicial (es decir, null ).
  • No responde adecuadamente a los errores . Por ejemplo, si por error asigna una cadena a window.onload , por ejemplo: window.onload = "test"; , no tirará ningún error. Tu código no funcionaría y sería muy difícil descubrir por qué. .addEventListener() sin embargo, generaría un error (al menos en Firefox): TypeError: Argumento 2 de EventTarget.addEventListener no es un objeto .
  • No proporciona una forma de elegir si desea controlar el evento en su fase de captura o propagación.

Controladores de eventos en línea ( onevent HTML de evento)

Ejemplo de código:

<a href="//google.com" onclick="event.preventDefault();">Try clicking this link.</a>

De manera similar a element.onevent , ahora está desanimado. Además de los problemas que tiene element.onevent , él:

  • Es un problema de seguridad potencial , ya que hace que XSS sea mucho más dañino. En la actualidad, los sitios web deben enviar el encabezado HTTP de la Content-Security-Policy para bloquear los scripts en línea y permitir los scripts externos solo de dominios de confianza. Consulte ¿Cómo funciona la política de seguridad de contenido?
  • No separa la estructura y la lógica del documento .
  • Si genera su página con una secuencia de comandos del lado del servidor y, por ejemplo, genera cien enlaces, cada uno con el mismo controlador de eventos en línea, su código sería mucho más largo que si el controlador de eventos se definiera solo una vez. Eso significa que el cliente tendría que descargar más contenido y, en consecuencia, su sitio web sería más lento.

Ver también


Javascript tiende a mezclar todo en objetos y eso puede hacer que sea confuso. Todo en uno es la forma de JavaScript.

Esencialmente onclick es un atributo HTML. A la inversa, addEventListener es un método en el objeto DOM que representa un elemento HTML.

En los objetos de JavaScript, un método es simplemente una propiedad que tiene una función como un valor y que funciona en contra del objeto al que está vinculado (usando esto por ejemplo).

En JavaScript, como elemento HTML representado por DOM, sus atributos se asignarán a sus propiedades.

Aquí es donde la gente se confunde porque JavaScript fusiona todo en un solo contenedor o espacio de nombres sin una capa de direccionamiento indirecto.

En un diseño de OO normal (que al menos fusiona el espacio de nombres de propiedades / métodos) podría tener algo como:

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

Hay variaciones como que podría usar un getter / setter para onload o HashMap para atributos, pero en última instancia eso es lo que vería. JavaScript eliminó esa capa de direccionamiento indirecto ante la expectativa de saber qué es lo que entre otras cosas. Se fusionaron domelement y atributos juntos.

A menos que sea compatible, debe utilizar addEventListener como práctica recomendada. Como otras respuestas hablan de las diferencias en ese sentido en lugar de las diferencias programáticas fundamentales, lo renunciaré. Esencialmente, en un mundo ideal solo debes usarlo en * desde HTML, pero en un mundo aún más ideal, no deberías hacer nada de eso desde HTML.

¿Por qué es dominante hoy? Es más rápido de escribir, más fácil de aprender y tiende a funcionar.

El punto principal de la carga en HTML es dar acceso al método o la funcionalidad addEventListener en primer lugar. Al usarlo en JS, está pasando por HTML cuando podría estar aplicándolo directamente.

Hipotéticamente puedes hacer tus propios atributos:

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

Lo que hace JS es un poco diferente a eso.

Puedes igualarlo a algo como (para cada elemento creado):

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

Los detalles reales de la implementación probablemente diferirán con un rango de variaciones sutiles que hacen que los dos sean ligeramente diferentes en algunos casos, pero eso es lo esencial.

Podría decirse que es un truco de compatibilidad que puede anclar una función a un atributo on, ya que los atributos predeterminados son todas las cadenas.


La diferencia que puedes ver si tienes otro par de funciones:

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

Las funciones 2, 3 y 4 funcionan, pero 1 no. Esto se debe a que addEventListener no sobrescribe los controladores de eventos existentes, mientras que onclick anula los controladores de eventos existentes onclick = fn .

La otra diferencia significativa, por supuesto, es que onclick siempre funcionará, mientras que addEventListener no funciona en Internet Explorer antes de la versión 9. Puede usar el attachEvent análogo (que tiene una sintaxis ligeramente diferente) en IE <9.


Mientras que onclick funciona en todos los navegadores, addEventListener no funciona en versiones anteriores de Internet Explorer, que en attachEvent lugar usa attachEvent .

La desventaja de onclick es que solo puede haber un controlador de eventos, mientras que los otros dos activarán todas las devoluciones de llamada registradas.


Por lo que sé, el evento de "carga" de DOM aún funciona muy limitado. Eso significa que solo se activará para el window object de la window object , las images y los elementos <script> , por ejemplo. Lo mismo ocurre con la asignación de onload directa. No hay diferencia técnica entre esos dos. Probablemente .onload = tenga una mejor disponibilidad en .onload = navegadores.

Sin embargo, no puede asignar un load event a un elemento <div> o <span> o lo que sea.


Según MDN , la diferencia es la siguiente:

addEventListener:

El método EventTarget.addEventListener () agrega el objeto especificado compatible con EventListener a la lista de escuchas de eventos para el tipo de evento especificado en el EventTarget en el que se llama. El objetivo del evento puede ser un elemento en un documento, el documento mismo, una ventana o cualquier otro objeto que admita eventos (como XMLHttpRequest).

al hacer clic:

La propiedad onclick devuelve el código del controlador de eventos de clic en el elemento actual. Cuando use el evento de clic para desencadenar una acción, también considere agregar esta misma acción al evento de reducción de teclas, para permitir el uso de esa misma acción por parte de personas que no usan un mouse o una pantalla táctil. Sintaxis element.onclick = functionRef; donde functionRef es una función, a menudo un nombre de una función declarada en otro lugar o una expresión de función. Consulte la "Guía de JavaScript: Funciones" para obtener más información.

También hay una diferencia de sintaxis en el uso, como se ve en los siguientes códigos:

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


Si no está demasiado preocupado por el soporte del navegador, hay una manera de volver a vincular la referencia ''this'' en la función llamada por el evento. Normalmente apuntará al elemento que generó el evento cuando se ejecuta la función, que no siempre es lo que desea. La parte difícil es poder al mismo tiempo eliminar el mismo detector de eventos, como se muestra en este ejemplo: 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); } }

El código anterior funciona bien en Chrome, y es probable que haya algún problema al hacer que "bind" sea compatible con otros navegadores.


También debería ser posible extender el oyente mediante un prototipo (si tenemos una referencia a él y no es una función anónima), o haga que la llamada ''onclick'' sea una llamada a una biblioteca de funciones (una función que llama a otras funciones)

me gusta

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

esto significa que nunca debemos cambiar la llamada onclick, solo debe alterar la función myFunctionList () para hacer lo que queramos, pero esto nos deja sin control de las fases de burbujeo / captura, por lo que debe evitarse en los navegadores más nuevos.

En caso de que alguien encuentre este hilo en el futuro ...


addEventListener permite configurar varios controladores, pero no es compatible con IE8 o inferior.

IE tiene attachEvent , pero no es exactamente lo mismo.