Эта статья нуждается в техническом обзоре. Как вы можете помочь.
Эта статья нуждается в редакционном обзоре. Как вы можете помочь.
Метод EventTarget.addEventListener()
регистрирует определенный обработчик события, вызванного на EventTarget
.
EventTarget
должен быть либо существующим элементом в документе, либо Document
, либо Window
, либо любым другим объектом, который поддерживает события (такой, как XMLHttpRequest
).
Синтаксис
target.addEventListener(type, listener[, useCapture]);
target.addEventListener(type, listener[, useCapture, wantsUntrusted ]); // только Gecko/Mozilla
type
- Строка, представляющая тип прослушиваемого события.
listener
- Объект, который принимает уведомление, когда событие указанного типа произошло. Это должен быть объект, реализующий интерфейс
EventListener
или просто функция JavaScript. useCapture
Необязательный- Если равно
true
,useCapture
указывает, что пользователь желает начать захват. После инициализации захвата все события указанного типа будут отправлены в зарегистрированныйlistener
перед отправкой в какой-либоEventTarget
под ним в дереве DOM. События, восходящие вверх по дереву, не будут вызывать слушателей, которым назначено использовать захват. Смотрите DOM Level 3 Events для более детального объяснения. ЗначениеuseCapture
по умолчанию равноfalse
.Note: For event listeners attached to the event target; the event is in the target phase, rather than capturing and bubbling phases. Events in the target phase will trigger all listeners on an element regardless of theuseCapture
parameter.Note:useCapture
became optional only in more recent versions of the major browsers; for example, it was not optional prior to Firefox 6. You should provide this parameter for broadest compatibility. wantsUntrusted
- Если равно
true
, слушатель будет получать сгенерированные события, посланные со страницы (по умолчанию равноfalse
для chrome иtrue
для обычных веб-страниц). Этот параметр доступен только в Gecko и в основном полезен для использования в аддонах и самом браузере. Смотрите Interaction between privileged and non-privileged pages для примеров использования.
Пример
Добавление простого слушателя
HTML Content
<table id="outside"> <tr><td id="t1">один</td></tr> <tr><td id="t2">два</td></tr> </table>
JavaScript Content
// Функция изменяет содержимое t2 function modifyText() { var t2 = document.getElementById("t2"); if (t2.firstChild.nodeValue == "три") { t2.firstChild.nodeValue = "два"; } else { t2.firstChild.nodeValue = "три"; } } // Добавляет слушателя событий для таблицы var el = document.getElementById("outside"); el.addEventListener("click", modifyText, false);
В примере выше, modifyText()
регистрирует слушателя для события click, используя addEventListener()
. Клик в любом месте таблицы будет поднимать обработчик и запускать modifyText()
.
Если вам нужно передать параметры в слушателя, вы можете использовать анонимные функции.
Слушатель события с анонимной функцией
HTML Content
<table id="outside"> <tr><td id="t1">один</td></tr> <tr><td id="t2">два</td></tr> </table>
JavaScript Content
// Функция, изменяющая содержание t2 function modifyText(new_text) { var t2 = document.getElementById("t2"); t2.firstChild.nodeValue = new_text; } // Функция, добавляющая слушатель к таблице el = document.getElementById("outside"); el.addEventListener("click", function(){modifyText("четыре")}, false);
Заметки
Зачем использовать addEventListener
?
addEventListener
- это способ зарегистрировать обработчик события, описанный в документации W3C DOM. Вот список преимуществ его использования:
- Позволяет добавлять множество обработчиков для одного события. Это особенно полезно для DHTML библиотек или Mozilla extensions, которые должны работать в условиях использования сторонних библиотек/расширений.
- Предоставляет точный контроль фазы срабатывания(вызова) обработчика (захват или всплытие)
- Срабатывает на любом DOM элементе, а не только на HTML элементах.
Ниже описан другой, более старый способ регистрации обработчиков.
Добавление слушателя во время обработки события
Если EventListener
добавлен к EventTarget
во время обработки события, он не будет вызван текущими действиями, но может быть вызван на более поздней стадии обработки события, при восходящей обработке.
Несколько одинаковых слушателей события
Если зарегистрировано несколько одинаковых EventListener
s на одном EventTarget
с одинаковыми параметрами, дублирующиеся слушатели игнорируются. Они не позволяют EventListener'у
быть вызванным дважды, и так как одинаковые слушатели игнорируются, не требуется удалять их вручную с помощью метода removeEventListener.
Значение this
в обработчике
Обычно желательно передавать элемент, на котором сработал обработчик события, например, при использовании обобщённых обработчиков для схожих элементов. При добавлении функции при помощи addEventListener()
значение переменной this
меняется — заметьте, что значение this
передаётся в функцию от вызывающего объекта.
В примере выше значение переменной this
внутри modifyText()
при вызове событием клика равно на таблицу 't'. Это противоположно поведению, которое возникает, если обработчик добавлен в HTML-разметке:
<table id="t" onclick="modifyText();"> . . .
Значение переменной this
внутри modifyText()
при вызове событием клика будет равно ссылке на глобальный (window) объект (или undefined
при использовании strict mode)
Function.prototype.bind()
, который позволяет указать значение, которое должно быть использовано для всех вызовов данной функции. Он позволяет вам легко обходить ситуации, в которых не ясно, чему будет равно this, в зависимости от того, в каком контексте будет вызвана ваша функция. заметьте, также, что Вам будет необходимо иметь внешню ссылку на слушатель, чтобы Вы могли удалить его позже.Пример с использованием bind
и без него:
var Something = function(element) { this.name = 'Something Good'; this.onclick1 = function(event) { console.log(this.name); // undefined, так как this является элементом }; this.onclick2 = function(event) { console.log(this.name); // 'Something Good', так как в this передано значение объекта Something }; element.addEventListener('click', this.onclick1, false); element.addEventListener('click', this.onclick2.bind(this), false); // Trick }
Проблема в примере выше заключается в том, что Вы не можете удалить слушатель, вызванный с with bind
. Другое решение использует специальную функцию handleEvent,
чтобы перехватывать любые события:
var Something = function(element) { this.name = 'Something Good'; this.handleEvent = function(event) { console.log(this.name); // 'Something Good', так как this является объектом Something switch(event.type) { case 'click': // код обработчика... break; case 'dblclick': // код обработчика... break; } }; // В этом случае слушатели хранятся в this, а не в this.handleEvent element.addEventListener('click', this, false); element.addEventListener('dblclick', this, false); // Вы можете напрямую удалять слушатели element.removeEventListener('click', this, false); element.removeEventListener('dblclick', this, false); }
Наследство Internet Explorer и attachEvent
В Internet Explorer младше 9 версии, вы можете использовать attachEvent вместо стандартного addEventListener. Для поддержки IE, пример выше может быть модифицирован следующим образом:
if (el.addEventListener) { el.addEventListener('click', modifyText, false); } else if (el.attachEvent) { el.attachEvent('onclick', modifyText); }
У attachEvent
есть недостаток: this будет ссылаться на объект window, а не на элемент, на котором он был вызван.
Совместимость
Вы можете обойти методы the addEventListener
, removeEventListener
, Event.preventDefault
и Event.stopPropagation
не поддерживаемы в IE 8 используя следующий код в началеВашего скрипта. Этот код подерживает использование handleEvent
и события DOMContentLoaded
.
Note: useCapture не поддерживается, так как IE 8 не имеет альтернативного метода для этого. также заметьте, что следующий код только добавляет поддержку IE 8. Также, он работает только при соблдении стандартов: объявление DOCTYPE страницы обязательно.
(function() { if (!Event.prototype.preventDefault) { Event.prototype.preventDefault=function() { this.returnValue=false; }; } if (!Event.prototype.stopPropagation) { Event.prototype.stopPropagation=function() { this.cancelBubble=true; }; } if (!Element.prototype.addEventListener) { var eventListeners=[]; var addEventListener=function(type,listener /*, useCapture (will be ignored) */) { var self=this; var wrapper=function(e) { e.target=e.srcElement; e.currentTarget=self; if (listener.handleEvent) { listener.handleEvent(e); } else { listener.call(self,e); } }; if (type=="DOMContentLoaded") { var wrapper2=function(e) { if (document.readyState=="complete") { wrapper(e); } }; document.attachEvent("onreadystatechange",wrapper2); eventListeners.push({object:this,type:type,listener:listener,wrapper:wrapper2}); if (document.readyState=="complete") { var e=new Event(); e.srcElement=window; wrapper2(e); } } else { this.attachEvent("on"+type,wrapper); eventListeners.push({object:this,type:type,listener:listener,wrapper:wrapper}); } }; var removeEventListener=function(type,listener /*, useCapture (will be ignored) */) { var counter=0; while (counter<eventListeners.length) { var eventListener=eventListeners[counter]; if (eventListener.object==this && eventListener.type==type && eventListener.listener==listener) { if (type=="DOMContentLoaded") { this.detachEvent("onreadystatechange",eventListener.wrapper); } else { this.detachEvent("on"+type,eventListener.wrapper); } eventListeners.splice(counter, 1); break; } ++counter; } }; Element.prototype.addEventListener=addEventListener; Element.prototype.removeEventListener=removeEventListener; if (HTMLDocument) { HTMLDocument.prototype.addEventListener=addEventListener; HTMLDocument.prototype.removeEventListener=removeEventListener; } if (Window) { Window.prototype.addEventListener=addEventListener; Window.prototype.removeEventListener=removeEventListener; } } })();
Старый способ регистрации обработчиков событий
addEventListener()
был добавлен в спецификации DOM 2 Events. До этого слушатели добавлялись следующим образом:
// Передача ссылки на функцию — не добавляйте '()' после него, это вызовет функцию! el.onclick = modifyText; // Использование функционального выражения element.onclick = function() { // ... логика функции ... };
Этот метод заменяет текущие слушатели события click
, если они есть. Тоже самое для других событий и ассоциируемых с ними обработчиков, таких как blur
(onblur
), keypress
(onkeypress
), и так далее.
Так как это по существу было частью DOM 0, этот метод имеет широкую поддержкуи не требует специального кросс-браузерного кода; следовательно, это обычно используется, чтобы добавлять слушатели динамически, если не требуются расширенные возможности addEventListener()
.
Вопросы памяти
var i; var els = document.getElementsByTagName('*'); // Случай 1 for(i=0 ; i<els.length ; i++){ els[i].addEventListener("click", function(e){/*некоторые действия*/}, false); } // Случай 2 function processEvent(e){ /*некоторые действия*/ } for(i=0 ; i<els.length ; i++){ els[i].addEventListener("click", processEvent, false); }
В первом случае новая (анонимная) функция создаётся при каждом шаге цикла. Во втором случае одна заранее объявленная функция используется как обработчик события. Из этого следует меньшее потребление памяти. Более того, в первом случае, вследствие отсутствия ссылок на анонимные функции, невозможно вызвать element.removeEventListener,
потому что нет ссылки на обработчик, в том время, как во стором случае возможно вызвать myElement.removeEventListener("click", processEvent, false)
.
Совместимость
Feature | Chrome | Firefox (Gecko) | Internet Explorer | Opera | Safari (WebKit) |
---|---|---|---|---|---|
Basic support | 1.0 | 1.0 (1.7 или ранее) | 9.0 | 7 | 1.0 |
useCapture made optional |
1.0 | 6.0 | 9.0 | 11.60 | (Да) |
Feature | Android | Firefox Mobile (Gecko) | IE Mobile | Opera Mobile | Safari Mobile |
---|---|---|---|---|---|
Basic support | 1.0 | 1.0 (1.0) | 9.0 | 6.0 | 1.0 |
Заметки по Gecko
- До Firefox 6, браузер выбросит исключение, если параметр
useCapture
не был точно равенfalse
. До Gecko 9.0 (Firefox 9.0 / Thunderbird 9.0 / SeaMonkey 2.6),addEventListener()
выбросит исключение, если параметрlistener
был равенnull
; сейчас метод завершается без ошибки, но ничего не делает.
Заметки по WebKit
- Несмотря на то, что в WebKit параметр
useCapture
был объявлен необязательным только в июне 2011 года, это работало и до этого изменения. Новые изменения были добавлены в Safari 5.1 и Chrome 13.
Смотрите также
EventTarget.removeEventListener()
- Creating and triggering custom events
- More details on the use of
this
in event handlers