Prawidłowe użycie addEventListener () / attachEvent ()?

81

Zastanawiam się jak addEventListenerodpowiednio attachEventpoprawnie używać ?

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

 // ...

lub

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

 // ...

?

Czy ta przeglądarka jest bezpieczna, czy też powinienem wybrać coś takiego:

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

I: Powiedz, że myfunc2dotyczy tylko przeglądarki IE 7. Jak odpowiednio zmodyfikować właściwą / preferowaną metodę?

ginny
źródło
Możesz mnie nie lubić za to, że to mówię, ale dlaczego po prostu nie użyjesz frameworka do rozwiązywania takich problemów?
Pointy
Chciałbym, ale nie mogę w tym przypadku. Czy możesz mi w tym pomóc, proszę?
ginny
@ginny Spójrz na moją odpowiedź. Daj mi znać, jeśli potrzebujesz dalszych wyjaśnień.
hitautodestruct
1
Przynajmniej nie powinieneś testować modelu zdarzenia za każdym razem , gdy chcesz zarejestrować wydarzenie. Można to łatwo podzielić na wspólną funkcję, do której należy przekazać element , typ zdarzenia i procedurę obsługi .
MrWhite

Odpowiedzi:

132

Użycie obu jest podobne, chociaż oba przyjmują nieco inną składnię dla parametru zdarzenia:

addEventListener ( odwołanie do mdn ):

Obsługiwane przez wszystkie główne przeglądarki (FF, Chrome, Edge)

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

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

Lista wydarzeń dla addEventListener.

attachEvent ( odwołanie do msdn ):

Obsługiwane przez IE 5-8 *

obj.attachEvent('onclick', callback);

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

Lista wydarzeń dla attachEvent.

Argumenty

Dla obu metod argumenty są następujące:

  1. To typ wydarzenia.
  2. Jest funkcją, która ma zostać wywołana po wyzwoleniu zdarzenia.
  3. ( addEventListenertylko) Jeśli prawda, wskazuje, że użytkownik chce zainicjować przechwytywanie .

Wyjaśnienie

Obie metody służą do osiągnięcia tego samego celu, jakim jest przypisanie zdarzenia do elementu.
Różnica polega na tym, że attachEventmoże być używany tylko w starszych silnikach renderujących trójząb ( IE5 + IE5-8 *) i addEventListenerjest to standard W3, który jest zaimplementowany w większości innych przeglądarek (FF, Webkit, Opera, IE9 +).

Aby zapewnić solidną obsługę zdarzeń w różnych przeglądarkach, w tym normalizacje, których nie uzyskasz w rozwiązaniu Diaz, użyj frameworka .

* IE9-10 obsługuje obie metody w celu zapewnienia zgodności wstecznej.

Podziękowania dla Luke'a Pupletta za wskazanie, że attachEventzostał usunięty z IE11.

Minimalna implementacja w różnych przeglądarkach

Zgodnie z zaleceniami Smitty , powinieneś przyjrzeć się temu addEvent Dustin Diaz, aby uzyskać solidną implementację w różnych przeglądarkach bez użycia frameworka:

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
źródło
@CamiloMartin Zawsze warto udzielić dobrej odpowiedzi, jeśli potem dostaniesz taki komentarz, dzięki :)
hitautodestruct
13
addEventListenerjest również obsługiwany przez IE9 +.
MrWhite
1
AttachEvent zostało usunięte w IE11, więc kod, który wykrywa IE i używa tego API, teraz zakończy się niepowodzeniem. Jeszcze nie widziałem, aby to się stało, ale zauważyłem, że podszywanie się pod ciąg agenta IE10 z IE11 może powodować błędy skryptu.
Luke Puplett
@LukePuplett Implementacja dustin diaz opiera się na wykrywaniu funkcji, a nie wykrywaniu przeglądarki. Czy to jest to, o czym mówisz?
hitautodestruct
7

Każdy, kto nadal bierze udział w tej dyskusji i nie znajduje odpowiedzi, której szukał do kasy:
http://dustindiaz.com/rock-solid-addevent

To jedno z najbardziej eleganckich rozwiązań, jakie znalazłem dla tych z nas, którzy mają ograniczenia w używaniu frameworków.

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
źródło