Правильне використання 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. Як відповідно змінити правильний / бажаний метод?


Можливо, ви мені не подобаєтесь, коли я це кажу, але чому б вам просто не використовувати фреймворк для вирішення таких питань?
Пойнті

Я б, але не можу в цьому випадку. Тож, не могли б ви допомогти мені в цьому, будь ласка?
Джинні

@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.