Правильное использование addEventListener () / attachEvent ()?


81

Интересно, как addEventListenerсоответственно attachEventправильно пользоваться?

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

 // ...

или же

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

 // ...

?

Безопасен ли этот кроссбраузер или мне лучше выбрать что-то вроде этого:

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

И: Допустим myfunc2, только для IE 7. Как соответственно изменить правильный / предпочтительный метод?


Возможно, вам не понравится, что я говорю это, но почему бы вам просто не использовать фреймворк для решения таких проблем?
Pointy

Я бы хотел, но не могу в этом случае. Не могли бы вы мне с этим помочь, пожалуйста?
Джинни

@ginny Посмотри на мой ответ. Дайте мне знать, если вам понадобятся какие-либо дополнительные объяснения, кроме этого.
hitautodestruct

1
По крайней мере, вам не следует тестировать модель событий каждый раз, когда вы хотите зарегистрировать событие. Это можно легко разделить на общую функцию, в которую вы передадите элемент , тип события и обработчик .
MrWhite

Ответы:


132

Оба используются аналогично, хотя оба имеют немного другой синтаксис для параметра события:

addEventListener ( ссылка на mdn ):

Поддерживается всеми основными браузерами (FF, Chrome, Edge)

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

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

Список событий для addEventListener.

attachEvent ( ссылка msdn ):

Поддерживается IE 5-8 *

obj.attachEvent('onclick', callback);

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

Список событий для attachEvent.

Аргументы

Для обоих методов аргументы следующие:

  1. Тип события.
  2. Функция, вызываемая после срабатывания события.
  3. ( addEventListenerтолько) Если true, указывает, что пользователь желает начать захват .

Объяснение

Оба метода используются для достижения одной и той же цели - привязки события к элементу.
Разница в том, что он attachEventможет использоваться только в старых движках рендеринга трезубца ( IE5 + IE5-8 *) и addEventListenerявляется стандартом W3, который реализован в большинстве других браузеров (FF, Webkit, Opera, IE9 +).

Для надежной поддержки кроссбраузерных событий, включая нормализацию, которую вы не получите с помощью решения Diaz, используйте фреймворк .

* IE9-10 поддерживает оба метода для обратной совместимости.

Спасибо Люку Пуплетту за указание на то, что attachEventон был удален из IE11.

Минимальная кроссбраузерная реализация

Как рекомендовал Смитти, вам следует взглянуть на этот addEvent Дастина Диаза для надежной кроссбраузерной реализации без использования фреймворка:

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


@CamiloMartin Всегда стоит дать хороший ответ, если потом вы получите такой комментарий, спасибо :)
hitautodestruct

13
addEventListenerтакже поддерживается IE9 +.
MrWhite

1
attachEvent было удалено в IE11, поэтому код, который обнаруживает IE и использует этот API, теперь не работает. Я еще не видел этого, но заметил, что подмена строки агента IE10 из IE11 может вызвать ошибки скрипта.
Люк Пуплетт,

@LukePuplett Реализация Dustin Diaz основана на обнаружении функций, а не на обнаружении браузера. Вы это имеете в виду?
hitautodestruct

7

Любой, кто все еще участвует в этом обсуждении и не находит ответа, который искал, оформить заказ:
http://dustindiaz.com/rock-solid-addevent

Это одно из самых элегантных решений, которые я нашел для тех из нас, у кого есть ограничения на использование фреймворков.

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);
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.