addEventListener vs onclick

Quelle est la différence entre addEventListener et onclick ?

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

le code ci-dessus réside ensemble dans un séparé .fichier js, et ils fonctionnent parfaitement.

527
demandé sur diraria 2011-06-14 22:49:54

14 réponses

les deux sont corrects, mais aucun d'eux n'est" meilleur " en soi, et il peut y avoir une raison pour laquelle le développeur a choisi d'utiliser les deux approches.

Écouteurs d'Événement (addEventListener et IE attachEvent)

les versions précédentes D'Internet Explorer implémentent javascript différemment de presque tous les autres navigateurs. Avec les versions de moins de 9, vous utilisez la méthode attachEvent [ doc ], comme ceci:

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

dans la plupart des autres navigateurs (y compris IE 9 et au-dessus), vous utilisez addEventListener [ doc ], comme ceci:

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

en utilisant cette approche ( DOM Level 2 events ), vous pouvez attacher un nombre théoriquement illimité d'événements à un seul élément. La seule limite pratique est la mémoire côté client et les autres problèmes de performance, qui sont différents pour chaque navigateur.

les exemples ci-dessus représentent l'utilisation d'une fonction anonyme [ doc ]. Vous pouvez également ajouter un écouteur d'événements en utilisant une référence de fonction[ doc ] ou une fermeture [ doc ]:

var myFunctionReference = function() { /* do stuff here*/ }

element.attachEvent('onclick', myFunctionReference);
element.addEventListener('click', myFunctionReference , false);

une autre caractéristique importante de addEventListener est le paramètre final, qui contrôle la façon dont l'auditeur réagit aux événements de bouillonnement [ doc ]. J'ai passé faussement dans les exemples, ce qui est standard pour probablement 95% des cas d'utilisation. Il n'y a pas d'argument équivalent pour attachEvent , ou lors de l'utilisation d'événements inline.

Inline événements (HTML onclick=" propriété" et de l'élément.onclick)

dans tous les navigateurs qui prennent en charge javascript, vous pouvez mettre un écouteur d'événements en ligne, c'est-à-dire directement dans le code HTML. Vous avez probablement vu ceci:

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

les développeurs les plus expérimentés évitent cette méthode, mais cela permet de faire le travail; c'est simple et direct. Vous ne pouvez pas utiliser des fermetures ou des fonctions anonymes ici (bien que le handler lui-même soit une fonction anonyme de toutes sortes), et votre contrôle de scope est limité.

l'autre méthode que vous mentionnez:

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

... est l'équivalent de javascript en ligne sauf que vous avez plus de contrôle de la portée (puisque vous écrivez un script plutôt que HTML) et peut utiliser des fonctions anonymes, fonction références, et / ou fermetures.

l'inconvénient important avec les événements inline est que contrairement aux écouteurs d'événements décrits ci-dessus, vous pouvez n'avoir qu'un seul événement inline assigné. Les événements Inline sont stockés comme un attribut / propriété de l'élément [ doc ], ce qui signifie qu'il peut être écrasé.

en utilisant l'exemple <a> du HTML ci-dessus:

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

... lorsque vous avez cliqué sur l'élément, vous feriez seulement consultez "Fait un truc #2" - vous a remplacé le premier affecté onclick de la propriété avec la deuxième valeur, et vous a remplacé l'original inline HTML onclick bien trop. Regardez ici: http://jsfiddle.net/jpgah / .

Quel est le meilleur?

la question est une question de compatibilité et de nécessité du navigateur. Devez-vous actuellement joindre plus d'un événement à un élément? Serez-vous dans l'avenir? Les chances sont, vous. attachEvent et addEventListener sont nécessaires. Si non, une ligne d'événement fera l'affaire.

jQuery et d'autres cadres javascript encapsulent les différentes implémentations de navigateur des événements DOM de niveau 2 dans les modèles génériques de sorte que vous pouvez écrire le code compatible cross-browser sans avoir à vous soucier de L'histoire D'IE en tant que rebelle. Même code avec jQuery, tous cross-browser et prêt au rock:

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

Ne pas courir et obtenir un cadre juste pour cette chose, bien que. Vous pouvez facilement rouler votre propre petit utilitaire pour prendre soin des navigateurs plus anciens:

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

l'Essayer: http://jsfiddle.net/bmArj/

en tenant compte de tout cela, à moins que le script que vous regardez ne tienne compte des différences de navigateur d'une autre manière (en code non indiqué dans votre question), la partie en utilisant addEventListener ne fonctionnerait pas dans les versions D'IE inférieures à 9.

Documentation et lectures connexes

761
répondu Chris Baker 2013-06-04 06:44:31

La différence que vous pouvez voir si vous avez eu un autre couple de fonctions:

var h = document.getElementById('a');
h.onclick = doThing_1;
h.onclick = doThing_2;

h.addEventListener('click', doThing_3);
h.addEventListener('click', doThing_4);

fonctions 2, 3 et 4 fonctionne, mais 1 ne fonctionne pas. Cela est dû au fait que addEventListener n'écrase pas les gestionnaires d'événements existants, alors que onclick l'emporte sur les gestionnaires d'événements onclick = fn existants.

l'autre différence significative, bien sûr, est que onclick fonctionnera toujours, tandis que addEventListener ne fonctionne pas dans Internet Explorer avant la version 9. Vous pouvez utiliser la syntaxe analogue attachEvent (qui a légèrement différente) dans IE <9.

136
répondu lonesomeday 2018-06-05 23:05:05

dans cette réponse, je décrirai les trois méthodes de définition des gestionnaires D'événements DOM.

element.addEventListener()

exemple de Code:

const element = document.querySelector('a');
element.addEventListener('click', event => event.preventDefault(), true);
<a href="//google.com">Try clicking this link.</a>

element.addEventListener() a de multiples avantages:

  • vous permet d'enregistrer illimité events handlers et de les supprimer avec element.removeEventListener() .
  • A useCapture paramètre, qui indique si vous souhaitez gérer l'événement dans sa de capture ou de phase de bouillonnement . Voir: incapable de comprendre l'attribut useCapture dans addEventListener .
  • S'occupe de sémantique . Fondamentalement, cela rend l'enregistrement des gestionnaires d'événements plus explicite. Pour un débutant, un appel de fonction rend évident que quelque chose arrive , alors que attribuer event à une propriété de DOM element n'est pas intuitif.
  • vous permet de séparer la structure du document (HTML) et la logique (JavaScript) . Dans les applications web minuscules, il peut sembler ne pas avoir d'importance, mais il ne compte avec un plus grand projet. Il est beaucoup plus facile de maintenir un projet qui sépare structure et logique qu'un projet qui ne le fait pas.
  • élimine la confusion avec correct les noms d'événements. En raison de l'utilisation d'écouteurs d'événements en ligne ou l'attribution d'écouteurs d'événements .onevent propriétés des éléments DOM, beaucoup de programmeurs JavaScript inexpérimentés pense que le nom de l'événement est par exemple onclick ou onload . on est pas une partie de l'événement nom . Les noms d'événements corrects sont click et load , et c'est ainsi que les noms d'événements sont passés à .addEventListener() .
  • Travaille dans presque tous les navigateurs . Si vous avez encore à supporter IE <= 8, Vous pouvez utiliser a polyfill from MDN .

element.onevent = function() {} (par exemple: onclick , onload )

exemple de Code:

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

c'était une façon d'enregistrer les gestionnaires d'événements dans DOM 0. Il est maintenant découragé, car il:

  • vous permet d'enregistrer un seul event handler. Supprimer aussi le gestionnaire assigné n'est pas intuitif, car pour supprimer le gestionnaire d'événements assigné en utilisant cette méthode, vous devez revenir à l'état initial de la propriété onevent (i.e. null ).
  • N'est pas répondre à des erreurs "1519430920 de façon appropriée". Par exemple, si vous assignez par erreur une chaîne de caractères à window.onload , par exemple: window.onload = "test"; , elle ne jeter toutes les erreurs. Votre code ne marcherait pas et il serait très difficile de savoir pourquoi. .addEventListener() cependant, serait jeter de l'erreur (au moins dans Firefox): TypeError: Argument 2 de EventTarget.addEventListener n'est pas un objet .
  • ne fournit pas un moyen de choisir si vous voulez gérer l'événement dans sa phase de capture ou de bouillonnement.

Inline gestionnaires d'événements ( onevent attribut HTML)

exemple de Code:

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

comme element.onevent , il est maintenant découragé. Outre les questions que element.onevent a, il:

  • Est un problème de sécurité potentiel , parce qu'il fait XSS beaucoup plus dangereux. De nos jours, les sites web doivent envoyer l'en-tête HTTP Content-Security-Policy approprié pour bloquer les scripts en ligne et n'autoriser les scripts externes que depuis des domaines de confiance. Voir Comment le Contenu de la Politique de Sécurité du travail?
  • N'est pas document distinct de la structure et de la logique .
  • si vous générez votre page avec un script côté serveur, et par exemple si vous générez une centaine de liens, chacun avec le même gestionnaire d'événements en ligne, votre code serait beaucoup plus long que si le gestionnaire d'événements n'était défini qu'une seule fois. Cela signifie que le client devrait télécharger plus de contenu, et dans le résultat de votre site web serait plus lent.

Voir aussi

44
répondu Michał Perłakowski 2017-09-06 10:15:52

alors que onclick fonctionne dans tous les navigateurs, addEventListener ne fonctionne pas dans les anciennes versions D'Internet Explorer, qui utilise attachEvent à la place.

l'inconvénient de onclick est qu'il ne peut y avoir qu'un gestionnaire d'événements, alors que les deux autres vont virer tous les callbacks enregistrés.

16
répondu Magnar 2011-06-14 18:52:21

pour autant que je sache, L'événement DOM" load " ne fonctionne toujours que de manière très limitée. Cela veut dire qu'il ne s'allumera que pour les éléments window object , images et <script> par exemple. Il en va de même pour l'assignation directe onload . Il n'y a pas de différence technique entre les deux. Probablement .onload = a une meilleure disponibilité de navigateur croisé.

cependant, vous ne pouvez pas attribuer un load event à un élément <div> ou <span> ou autre.

12
répondu jAndy 2011-08-01 17:27:24

si vous n'êtes pas trop inquiet au sujet du support du navigateur, il y a un moyen de rebrancher la référence 'ceci' dans la fonction appelée par l'événement. Il sera normalement pointer vers l'élément qui a généré l'événement lorsque la fonction est exécutée, ce qui n'est pas toujours ce que vous voulez. La partie délicate est de pouvoir en même temps supprimer le même écouteur d'événements, comme indiqué dans cet exemple: 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);           
    }
}

le le code ci-dessus fonctionne bien dans GoogleChrome, et il y a sans doute des limites à rendre "bind" compatible avec d'autres navigateurs.

1
répondu Lars Rönnbäck 2014-03-14 09:36:58

utiliser des gestionnaires en ligne est incompatible avec Content Security Policy de sorte que l'approche addEventListener est plus sûre de ce point de vue. Bien sûr, vous pouvez activer les handlers en ligne avec unsafe-inline mais, comme son nom l'indique, ce n'est pas sûr car cela ramène toutes les hordes D'exploits JavaScript que le CSP empêche.

1
répondu kravietz 2015-04-20 16:40:15

un détail n'a pas encore été noté: les navigateurs de bureau modernes considèrent les différentes presses à boutons comme des" clics "pour AddEventListener('click' et onclick par défaut.

  • sur Chrome 42 et IE11, les deux onclick et AddEventListener cliquez sur feu sur le clic gauche et le clic du milieu.
  • Sur Firefox 38, onclick feux seulement sur le clic gauche, mais AddEventListener cliquez sur les feux sur la gauche, le milieu et droit de clics.

aussi, le comportement de clic moyen est très incohérent parmi les navigateurs lorsque les curseurs de défilement sont impliqués:

  • Sur Firefox, moyen-cliquez sur événements toujours le feu.
  • sur Chrome, ils ne tirent pas si le middleclick ouvre ou ferme un curseur de défilement.
  • sur IE, ils tirent quand le curseur se ferme, mais pas quand il s'ouvre.

il est également intéressant de noter que les événements" click "pour n'importe quel élément HTML sélectionnable au clavier tel que input tirent aussi sur l'espace ou entrent quand l'élément est sélectionné.

1
répondu a guest 2015-06-30 19:45:42

il devrait également être possible d'étendre l'auditeur en le prototypant (si nous avons une référence à lui et à sa fonction non anonyme) -ou faire l'appel "onclick" un appel à une bibliothèque de fonction (une fonction appelant d'autres fonctions)

comme

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

cela signifie que nous n'avons jamais à contester l'appel onclick juste modifier la fonction myFunctionList () pour faire ce que nous voulons, mais cela nous laisse sans contrôle de bouillonnement / capture les phases devrait donc être évité pour les navigateurs les plus récents.

juste au cas où quelqu'un trouve ce fil dans le futur...

1
répondu patrik 2015-07-25 20:49:04

selon MDN , la différence est la suivante:

addEventListener:

The EventTarget.la méthode addEventListener() ajoute la valeur spécifiée EventListener-objet compatible à la liste des écouteurs d'événements pour le type d'événement spécifié sur L'EventTarget sur lequel il est appelé. Le la cible d'événement peut être un élément d'un document, le Document lui-même, De la fenêtre, ou de toute autre objet qui supporte des événements (tels que XMLHttpRequest).

onclick:

la propriété onclick renvoie le code du gestionnaire d'événements sur le élément en cours. Lors de l'utilisation de l'événement click pour déclencher une action, aussi envisagez d'ajouter cette même action à l'événement keydown, pour permettre utilisation de la même action par des personnes qui n'utilisent pas une souris ou une touche écran. La syntaxe de l'élément.onclick = functionRef; où functionRef est un fonction souvent du nom d'une fonction déclarée ailleurs ou une fonction expression. Voir "JavaScript Guide: Functions" pour plus de détails.

il y a aussi une différence de syntaxe dans l'utilisation comme vous voyez dans les codes ci-dessous:



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);

onclick:

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!");
}
1
répondu Alireza 2018-03-08 12:10:44

addEventListener vous permet de définir plusieurs gestionnaires, mais n'est pas pris en charge dans IE8 ou inférieur.

c'est à dire n'avoir attachEvent , mais ce n'est pas exactement la même.

0
répondu user113716 2011-06-14 18:52:45

Javascript tend à tout mélanger dans des objets et cela peut le rendre confus. Tout en un est le JavaScript.

essentiellement onclick est un attribut HTML. À l'inverse, addEventListener est une méthode sur L'objet DOM représentant un élément HTML.

dans les objets JavaScript, une méthode est simplement une propriété qui a une fonction de valeur et qui fonctionne contre l'objet auquel elle est attachée (en utilisant ceci par exemple).

en JavaScript en tant qu'élément HTML représenté par DOM aura ses attributs cartographiés sur ses propriétés.

c'est là que les gens sont confus parce que JavaScript mélange tout dans un conteneur ou un espace de nom unique sans couche d'indirecte.

dans un layout oo normal (qui fusionne au moins l'espace de noms des propriétés/méthodes) vous pourriez avoir quelque chose comme:

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

il y a des variantes comme il pourrait utiliser un getter / setter pour onload ou HashMap pour les attributs, mais en fin de compte, c'est ce à quoi il ressemblerait. JavaScript a éliminé cette couche de l'indirecte à l'attente de savoir ce qui est entre autres choses. Il fusionne domElement et attributes.

sauf compatibilité, vous devriez comme une pratique exemplaire utiliser addEventListener. Alors que d'autres réponses évoquent les différences à cet égard plutôt que les différences fondamentales en matière de programmes, je vais l'oublier. Essentiellement, dans un monde idéal vous êtes vraiment destiné à utiliser sur* de HTML mais dans un monde encore plus idéal vous ne devriez pas faire quelque chose comme ça à partir de HTML.

Pourquoi est-il dominant aujourd'hui? C'est plus rapide à écrire, facile à apprendre et tend simplement.

le point entier de onload en HTML est de donner accès à la méthode addEventListener ou à la fonctionnalité en premier lieu. En l'utilisant dans JS vous passez par HTML quand vous pourriez l'appliquer directement.

Hypothétiquement vous pouvez faire vos propres attributs:

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

ce que JS fait avec est un peu différent de cela.

vous pouvez l'assimiler à quelque chose comme (pour chaque élément créé):

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

les détails réels de la mise en œuvre seront probablement différents avec une gamme de variations subtiles rendant les deux légèrement différents dans certains cas, mais c'est l'essence de celui-ci.

C'est sans doute un hack de compatibilité que vous pouvez épingler une fonction à un attribut on puisque par défaut les attributs sont toutes les chaînes.

0
répondu jgmjgm 2017-03-07 21:57:31

résumé:

  1. addEventListener peut ajouter plusieurs événements, alors qu'avec onclick cela ne peut pas être fait.
  2. onclick peut être ajouté en tant qu'attribut HTML , alors qu'un addEventListener ne peut être ajouté qu'à l'intérieur des éléments <script> .
  3. addEventListener peut prendre un troisième argument qui peut arrêter la propagation de l'évènement.

les deux peuvent être utilisés pour gérer des événements. Cependant, addEventListener devrait être le choix préféré car il peut faire tout onclick fait et plus. N'utilisez pas inline onclick comme attributs HTML car cela mélange le javascript et le HTML qui est une mauvaise pratique. Il rend le code moins supportable.

0
répondu Willem van der Veen 2018-08-25 09:48:17

le contexte référencé par le mot-clé 'this' en Javasscript est différent.

regardez le code suivant:

<!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>

Ce qu'il fait est vraiment simple. lorsque vous cliquez sur le bouton, le bouton sera désactivé automatiquement.

D'abord quand vous essayez de connecter les événements de cette façon button.onclick = function(), l'événement onclick sera déclenchée en cliquant sur le bouton, toutefois, le bouton ne sera pas désactivé car il n'y a pas de liaison explicite entre le bouton.onclick et gestionnaire d'événement onclick. Si vous déboguez voir l'objet 'this' , vous pouvez voir qu'il se réfère à l'objet 'window' .

deuxièmement, si vous commentez btnSubmit.onclick = disable(); et décommentez //btnSubmit.addEventListener('click', disable, false); vous pouvez voir que le bouton est désactivé parce que de cette façon il y a liaison explicite entre le bouton.l'événement onclick et gestionnaire d'événement onclick. Si vous déboguez dans la fonction disable, vous pouvez voir 'this' se réfère à la button control plutôt que le window .

C'est quelque chose que je n'aime pas chez JavaScript qui est incohérent. Btw, si vous utilisez jQuery( $('#btnSubmit').on('click', disable); ), il utilise la liaison explicite.

-1
répondu Larry 2014-01-13 01:02:23