Модель событий #
Событие — сигнал браузера о действии пользователя или изменении среды (клик, ввод, загрузка, изменение размера). Подписка через addEventListener связывает DOM-узел с функцией-обработчиком. Это базовый механизм кнопок плеера, переключателей виджетов и любых интерактивных элементов JSFlow.
addEventListener #
const playBtn = document.querySelector('.player__play')
function onPlayClick(event) {
console.log('воспроизведение', event.type)
}
playBtn.addEventListener('click', onPlayClick)
Третий аргумент — опции или boolean useCapture:
document.querySelector('.modal').addEventListener(
'keydown',
(event) => {
if (event.key === 'Escape') closeModal()
},
{ once: true } // снять после первого срабатывания
)
Полезные опции:
| Опция | Эффект |
|---|---|
capture: true | фаза перехвата, до целевого элемента |
once: true | автоматически удалить после вызова |
passive: true | не вызывать preventDefault (оптимизация scroll) |
signal | отписаться через AbortController |
Объект Event #
document.querySelector('.checkout-bar').addEventListener('click', (event) => {
event.type // "click"
event.target // элемент, на котором сработало событие
event.currentTarget // элемент, на котором висит listener (часто совпадает)
event.timeStamp
})
Для UI-кнопок с иконкой target может быть вложенный <svg>, а currentTarget — сама <button>.
preventDefault и stopPropagation #
document.querySelector('#newsletter-form').addEventListener('submit', (event) => {
event.preventDefault() // не перезагружать страницу
sendNewsletter(new FormData(event.target))
})
document.querySelector('.track-row a').addEventListener('click', (event) => {
event.stopPropagation() // не всплывать к родителю со своим обработчиком
})
preventDefault отменяет действие по умолчанию (переход по ссылке, submit). stopPropagation останавливает дальнейшее всплытие — используйте осознанно, чтобы не ломать делегирование на родителе.
removeEventListener #
Нужна та же ссылка на функцию, что при подписке:
function onResize() {
reflowDashboard()
}
window.addEventListener('resize', onResize)
window.removeEventListener('resize', onResize)
Анонимные стрелочные функции снять нельзя — именуйте обработчик или используйте { once: true } / AbortController:
const controller = new AbortController()
document.querySelector('.playlist').addEventListener(
'click',
handlePlaylistClick,
{ signal: controller.signal }
)
controller.abort() // все listeners с этим signal отписаны
Несколько обработчиков #
На один элемент можно повесить несколько listener’ов одного типа — они вызовутся в порядке регистрации:
const widget = document.querySelector('[data-widget="kpi"]')
widget.addEventListener('click', () => widget.classList.add('is-selected'))
widget.addEventListener('click', () => trackMetric('kpi_click'))
Дублирующая подписка той же функции дважды приведёт к двойному вызову.
Итог #
addEventListener(type, handler, options)— стандартная подписка на события.event.target— источник;event.currentTarget— элемент с listener.preventDefault— отмена действия браузера;stopPropagation— остановка всплытия.- Для отписки храните именованную функцию или
AbortSignal.