Источник addEventListener accepts functions and (!) objects
Чтобы создавать интерактивные веб-приложения нужно использовать события JavaScript. Как они работают?
Вы указываете нужный тип события, добавляете коллбэк, и теперь можете обрабатывать клики, нажатия клавиш, прокрутку и другие события.
Например, чтобы обработать нажатие кнопки, можно использовать следующий код:
document.querySelector('button')
.addEventListener('click', () => {
console.log('кнопка нажата');
});
Этот код обращается к DOM, находит указанный элемент, и добавляет обработчик события click используя addEventListener.
В соответствии с документацией DOM, target.addEventListener может иметь следующие параметры:
target.addEventListener(type, listener [, options]);
target.addEventListener(type, listener [, useCapture]);
target.addEventListener(type, listener [, useCapture, wantsUntrusted ]); // только в браузерах Gecko/Mozilla
addEventListener принимает: тип события, коллбэк и параметр options/useCapture. Подробнее о возможных значениях параметров в документации событий JavaScript.
Параметр listener может не только функцией но и объектом.
Обработка событий JavaScript с помощью addEventListener и EventListener
MDN описывает listener так:
listener может быть объектом реализующим интерфейс EventListener или JavaScript функцией
В ранней версии спецификации событий DOM (до HTML5), описан интерфейс EventListener. Реализующие его объекты должны содержать метод handeEvent. Они могут использоваться с addEventListener.
// класс, реализующий
// интерфейс `EventListener`
class EventHandler {
constructor() {
this.eventCount = 0;
}
handleEvent() {
this.eventCount++;
console.log(`Событие обработано ${this.eventCount} раз`);
}
}
document.querySelector('button')
.addEventListener('click', new EventHandler());
Это код класса EventHandler. Инициализированные объекты обработчиков событий могут быть переданы в addEventListener. Обработчик считает количество событий нужного типа. Попробуйте этот код на CodePen. Вся информация хранится в самом объекте и код работает без внешних переменных. Мне нравится этот паттерн, он пригодится для работы с последовательными событиями.
MDN говорит, что интерфейс EventListener поддерживается большинством браузеров и вы можете безопасно передавать реализующие его объекты в addEventListener. Когда их нужно передавать? Объясню на примере:
class MyComponent {
constructor (el) {
this.el = el
this.el.addEventListener('click', this)
}
handleEvent (event) {
console.log('my component элемент нажат')
}
destroy () {
this.el.removeEventListener('click', this)
}
}
const component = new MyComponent(
document.querySelector('button')
);
Конструктор класса MyComponent принимает элемент DOM в качестве аргумента и сам добавляет\удаляет его обработчики событий JavaScript. Класс реализует интерфейс EventListener, а следовательно вы можете передавать this в addEventListener.
***
Для того чтобы ваш интерфейс был удобным и интерактивным, важно не только использовать события JavaScript, но и учитывать размер области нажатия. Подробнее о том, как помочь юзеру не промахнуться, читайте в статье: «Хотел кликнуть, но не смог: как правильно настроить размер области клика».