Richtige Verwendung von addEventListener () / attachEvent ()?

81

Ich frage mich, wie man addEventListenerjeweils attachEventrichtig verwendet?

window.onload = function (myFunc1) { /* do something */ }

function myFunc2() { /* do something */ }

if (window.addEventListener) {
  window.addEventListener('load', myFunc2, false);
} else if (window.attachEvent) {
  window.attachEvent('onload', myFunc2);
}

 // ...

oder

function myFunc1() { /* do something */ }

if (window.addEventListener) {
  window.addEventListener('load', myFunc1, false);
} else if (window.attachEvent) {
  window.attachEvent('onload', myFunc1);
}

function myFunc2() { /* do something */ }

if (window.addEventListener) {
  window.addEventListener('load', myFunc2, false);
} else if (window.attachEvent) {
  window.attachEvent('onload', myFunc2);
}

 // ...

?

Ist dieser Cross-Browser sicher oder sollte ich besser so etwas machen:

function myFunc1(){ /* do something */ }
function myFunc2(){ /* do something */ }
// ...

function addOnloadEvent(fnc){
  if ( typeof window.addEventListener != "undefined" )
    window.addEventListener( "load", fnc, false );
  else if ( typeof window.attachEvent != "undefined" ) {
    window.attachEvent( "onload", fnc );
  }
  else {
    if ( window.onload != null ) {
      var oldOnload = window.onload;
      window.onload = function ( e ) {
        oldOnload( e );
        window[fnc]();
      };
    }
    else
      window.onload = fnc;
  }
}

addOnloadEvent(myFunc1);
addOnloadEvent(myFunc2);
// ...

AND: Say myfunc2ist nur für IE 7. Wie ändere ich die richtige / bevorzugte Methode entsprechend?

ginny
quelle
Sie mögen mich vielleicht nicht, weil ich das gesagt habe, aber warum würden Sie nicht einfach einen Rahmen verwenden, um solche Probleme zu lösen?
Pointy
Ich würde, aber ich kann in diesem Fall nicht. Könnten Sie mir bitte dabei helfen?
Ginny
@ginny Schau dir meine Antwort an. Lassen Sie mich wissen, wenn Sie weitere Erklärungen benötigen.
Hitautodestruct
1
Zumindest sollten Sie nicht jedes Mal , wenn Sie ein Ereignis registrieren möchten, auf das Ereignismodell testen . Dies kann leicht in eine gemeinsame Funktion unterteilt werden, an die Sie das Element , den Ereignistyp und den Handler übergeben .
MrWhite

Antworten:

132

Die Verwendung von beiden ist ähnlich, obwohl beide eine leicht unterschiedliche Syntax für den Ereignisparameter annehmen:

addEventListener ( MDN-Referenz ):

Unterstützt von allen gängigen Browsern (FF, Chrome, Edge)

obj.addEventListener('click', callback, false);

function callback(){ /* do stuff */ }

Ereignisliste für addEventListener.

attachEvent ( msdn Referenz ):

Unterstützt von IE 5-8 *

obj.attachEvent('onclick', callback);

function callback(){ /* do stuff */ }

Ereignisliste für attachEvent.

Argumente

Für beide Methoden lauten die Argumente wie folgt:

  1. Ist der Ereignistyp.
  2. Ist die Funktion, die aufgerufen werden soll, sobald das Ereignis ausgelöst wurde.
  3. ( addEventListenernur) Wenn true, wird angezeigt, dass der Benutzer die Erfassung starten möchte .

Erläuterung

Beide Methoden werden verwendet, um das gleiche Ziel zu erreichen, ein Ereignis an ein Element anzuhängen.
Der Unterschied besteht darin, dass attachEventnur ältere Trident- Rendering-Engines ( IE5 + IE5-8 *) verwendet werden können und addEventListenerein W3-Standard ist, der in den meisten anderen Browsern (FF, Webkit, Opera, IE9 +) implementiert ist.

Verwenden Sie für eine solide browserübergreifende Ereignisunterstützung, einschließlich Normalisierungen, die Sie mit der Diaz-Lösung nicht erhalten, ein Framework .

* IE9-10 unterstützt beide Methoden aus Gründen der Abwärtskompatibilität.

Vielen Dank an Luke Puplett für den Hinweis, dass attachEventIE11 entfernt wurde.

Minimale browserübergreifende Implementierung

Wie von Smitty empfohlen, sollten Sie sich dieses Dustin Diaz addEvent ansehen, um eine solide browserübergreifende Implementierung ohne Verwendung eines Frameworks zu erhalten:

function addEvent(obj, type, fn) {
  if (obj.addEventListener) {
    obj.addEventListener(type, fn, false);
  }
  else if (obj.attachEvent) {
    obj["e"+type+fn] = fn;
    obj[type+fn] = function() {obj["e"+type+fn](window.event);}
    obj.attachEvent("on"+type, obj[type+fn]);
  }
  else {
    obj["on"+type] = obj["e"+type+fn];
  }
}

addEvent( document, 'click', function (e) {
  console.log( 'document click' )
})

hitautodestruct
quelle
@CamiloMartin Es lohnt sich immer, eine gute Antwort einzugeben, wenn Sie danach einen Kommentar wie diesen erhalten. Danke :)
hitautodestruct
13
addEventListenerwird auch von IE9 + unterstützt.
MrWhite
1
attachEvent wurde in IE11 entfernt, sodass der Code, der den IE erkennt und diese API verwendet, jetzt fehlschlägt. Ich habe dies noch nicht gesehen, aber ich habe festgestellt, dass das Spoofing der IE10-Agentenzeichenfolge von IE11 zu Skriptfehlern führen kann.
Luke Puplett
@LukePuplett Die Implementierung von Dustin Diaz basiert auf der Funktionserkennung und nicht auf der Browsererkennung. Beziehen Sie sich darauf?
Hitautodestruct
7

Jeder, der noch an dieser Diskussion teilnimmt und keine Antwort findet, nach der er gesucht hat:
http://dustindiaz.com/rock-solid-addevent

Dies ist eine der elegantesten Lösungen, die ich für diejenigen von uns gefunden habe, die Einschränkungen bei der Verwendung der Frameworks haben.

function addEvent(obj, type, fn) {

    if (obj.addEventListener) {
        obj.addEventListener(type, fn, false);
        EventCache.add(obj, type, fn);
    } else if (obj.attachEvent) {
        obj["e" + type + fn] = fn;
        obj[type + fn] = function() {
            obj["e" + type + fn](window.event);
        }
        obj.attachEvent("on" + type, obj[type + fn]);
        EventCache.add(obj, type, fn);
    } else {
        obj["on" + type] = obj["e" + type + fn];
    }

}

var EventCache = function() {

    var listEvents = [];
    return {
        listEvents: listEvents,
        add: function(node, sEventName, fHandler) {
            listEvents.push(arguments);
        },
        flush: function() {
            var i, item;

            for (i = listEvents.length - 1; i >= 0; i = i - 1) {
                item = listEvents[i];
                if (item[0].removeEventListener) {
                    item[0].removeEventListener(item[1], item[2], item[3]);
                };

                if (item[1].substring(0, 2) != "on") {
                    item[1] = "on" + item[1];
                };

                if (item[0].detachEvent) {
                    item[0].detachEvent(item[1], item[2]);
                };

                item[0][item[1]] = null;
            };
        }
    };
}();

addEvent(window, 'unload', EventCache.flush);
Smitty
quelle