JavaScript – Введение в события. Обработчик события

В этой статье вы узнаете: что такое событие, способы задания обработчика (слушателя) событию, методы addEventListener
и removeEventListener
.
Что такое событие?
Событие – это определённый сигнал от браузера. Он сообщает нам о том, что что-то произошло.
Например: щелчок мыши, нажатие клавиши на клавиатуре, изменение размера области просмотра, завершение загрузки документа и т.д.
При этом сигнал всегда связан с объектом. Подавать сигналы могут различные объекты: window
, document
, DOM-элементы и т.д.
Список некоторых событий и их название:
DOMContentLoaded
– завершение загрузки DOM;click
– клик (нажатие левой кнопки мыши, на устройствах с сенсорным управлением возникает при касании);keydown
– нажатие клавиши на клавиатуре;resize
– изменение размеров документа;change
– окончание изменения значения в поле ввода.
Обработчик события
Зачем нам события? Они нам нужны для того, чтобы мы могли реагировать на них, или другими словами выполнять определённые действия, когда они произойдут.
В JavaScript это выполняется посредством привязывания некоторой функции к событию. После этого эта функция будет вызываться всякий раз, когда это событие на указанном элементе будет возникать. Эту функцию в JavaScript принято называть обработчиком события.
Следует отметить, что на странице постоянно возникает огромное количество событий, независимо от того назначили ли мы им обработчик или нет. Наша задача – это заставить наш сайт или приложение реагировать только на те события, которые нам небезразличны.
Способы задания событию обработчика
Назначить обработчик событию можно разными способами:
- через HTML-атрибут
on{событие}
(не является хорошей практикой); - посредством свойства DOM-элемента
on{событие}
; - используя специальный метод
addEventListener
.
Инициализация обработчика через атрибут
Этот способ позволяет прописать обработчик напрямую в разметке. Выполняется это посредством указания JavaScript кода в атрибуте on{событие}
. Вместо {событие}
необходимо написать имя (тип) события (например: click
).
Пример, в котором назначим HTML-элементу button
обработчик события click
, используя атрибут:
<!-- onclick - атрибут, содержащий код, который будет выполняться всякий раз при наступлении события click на этом элементе -->
<button type="button" onclick="alert(Date())">Текущая дата</button>
Если код, который нужно поместить в атрибут достаточно большой, то в этом случае его лучше оформить в виде функции, а в атрибут поместить её вызов.
Например:
<script>
// функция sum
function sum() {
const number1 = +document.querySelector('#number1').value;
const number2 = +document.querySelector('#number2').value;
const sum = number1 + number2;
document.querySelector('#answer').textContent = sum;
}
</script>
<input type="text" id="number1">
<input type="text" id="number2">
<div id="answer"></div>
<button type="button" onclick="sum()">Посчитать</button>
В этом примере мы указали в качестве обработчика функцию sum
.
При этом задавать обработчик напрямую в разметке не является хорошей практикой, т.к. это приведёт к смешиванию JavaScript и HTML кода.
Добавление обработчика через свойство DOM объекта
Второй способ назначить обработчик - это использовать свойство on{событие}
.
Например, привяжем обработчик события click
к элементу (для этого события свойство будет onclick
):
<!-- HTML код кнопки -->
<button type="button" id="my-btn">Нажми на меня</button>
<!-- Скрипт на JavaScript -->
<script>
// получим кнопку и сохраним ссылку на неё в переменную
const $btn = document.querySelector('#my-btn');
// добавим к $btn обработчик события click
$btn.onclick = function() {
alert('Вы кликнули на кнопку!');
}
</script>
В приведённом выше примере обработчик представляет собой анонимную функцию, которая будет выполняться всякий раз, когда это событие на указанном элементе будет происходить.
Другой вариант – это назначить уже существующую функцию.
Например:
function changeBgColor() {
document.body.style.backgroundColor = `rgb(${Math.round(Math.random()*255)}, ${Math.round(Math.random()*255)}, ${Math.round(Math.random()*255)})`;
}
document.onclick = changeBgColor;
Внутри обработчика можно обратиться к текущему элементу, т.е. к тому для которого в данный момент был вызван этот обработчик. Осуществляется это с помощью ключевого слова this
.
Например:
<!-- HTML код кнопок -->
<button type="button">Кнопка 1</button>
<button type="button">Кнопка 2</button>
<button type="button">Кнопка 3</button>
<!-- Скрипт на JavaScript -->
<script>
function message() {
// this - обращаемся к кнопке для которой вызван обработчик
alert(this.textContent);
}
// получим кнопки и сохраним ссылки на них в переменную $btns
const $btns = document.querySelectorAll('button');
// переберём кнопки и добавим к ним обработчик, используя onclick
$btns.forEach(function($element) {
$element.onclick = message;
});
</script>
Кстати, когда обработчик задаётся через атрибут, то браузер самостоятельно при чтении такого HTML создаёт из значения этого атрибута функцию и присваивает её одноименному свойству этого элемента.
Например:
<button id="btn" type="button" onclick="alert('Вы кликнули на кнопку')">Кнопка</button>
<script>
const $element = document.querySelector('#btn');
// получим значение свойства onclick (как видно браузер туда автоматически записал функцию, которую создал на основании содержимого этого атрибута)
console.log($element.onclick);
</script>

Т.е., по сути, задание свойства через атрибут – это просто способ инициализации обработчика. Т.к. сам обработчик в этом случае тоже хранится в свойстве DOM-объекта.
Но установка обработчика через свойство имеет недостаток. С помощью него нельзя назначить одному событию несколько обработчиков. Если в коде создадим новый обработчик, то он перезапишет существующий:
<button id="btn" type="button">Кнопка</button>
<script>
const $element = document.querySelector('#btn');
$element.onclick = function () {
alert(`id = ${this.id}`);
}
// заменит предыдущий обработчик
$element.onclick = function () {
alert(`text = ${this.textContent}`);
}
</script>
Кстати, также не получится назначить несколько обработчиков, один через атрибут, а другой через свойство. Последний перепишет предыдущий.
<button id="btn" type="button" onclick="alert(`id = ${this.id}`);">Кнопка</button>
<script>
const $element = document.querySelector('#btn');
// заменит обработчик, инициализированный с помощью атрибута
$element.onclick = function () {
alert(`text = ${this.textContent}`);
}
</script>
Подписка на событие через addEventListener
Ещё один способ назначить событию обработчик — это использовать метод addEventListener
.
Синтаксис addEventListener
:
// $element - объект или DOM-элемент к которому нужно добавить обработчик
$element.addEventListener(event, handler[, options]);
Параметры:
event
- имя события (например,click
);handler
- функция, которая будет вызвана при возникновении этого события;;options
(не обязательный) - объект, в котором можно задать дополнительные параметры.
В options
можно задать:
once
- еслиtrue
, то обработчик будет вызван всего один раз;capture
- задаёт фазу, на которой нужно вызвать обработчик события (по умолчанию - на этапе всплытия); если нужно на этапе погружения (перехвата) - то этому ключу следует установить значениеtrue
;passive
- определяет, следует ли вызыватьpreventDefault()
; если установитьtrue
- то обработчик никогда не вызовет этот метод.
Кроме этого, options
можно установить true
или false
, в этом случае он будет просто определять фазу (всплытие или погружение).
Пример:
function changeBgColor() {
document.body.style.backgroundColor = '#3f51b5';
}
document.addEventListener('click', changeBgColor, false);
В этом примере addEventListener
прикреплен к объекту document
. Когда событие click
возникнет на этом элементе, будет вызвана функция changeBgColor
.
Если мы откроем документ, содержащий этот код в браузере, то сначала увидим пустую страницу.

Однако при клике фон страницы изменится с белого на #3f51b5
.

Иногда возникают ситуации, когда нужно удалить обработчик. Это можно выполнить, используя removeEventListener
:
$element.removeEventListener(event, handler[, options]);
Этот метод принимает аргументы тех же типов, что addEventListener
.
При этом чтобы, удалить обработчик, нам нужно указать точно такие же аргументы, которые мы использовали при его назначении.
function changeBgColor() {
document.body.style.backgroundColor = '#3f51b5';
}
document.addEventListener('click', changeBgColor, false);
document.removeEventListener('click', changeBgColor, false);
Если обработчик - анонимная функция, то её удалить нельзя.
document.addEventListener('click', function() {
document.body.style.backgroundColor = '#3f51b5';
});
// удалить обработчик установленный выше с помощью addEventListener не получится, т.к. это разные функции, имеющие одинаковый код
document.removeEventListener('click', function() {
document.body.style.backgroundColor = '#3f51b5';
});
Как добавить несколько обработчиков к событию?
Метод addEventListener
в отличие от предыдущих способов позволяет назначить одному событию несколько обработчиков:
function handler1() { ... }
function handler2() { ... }
document.addEventListener('click', handler1);
document.addEventListener('click', handler2);
Как правильно прикрепить обработчики к элементам?
Для прикрепления обработчиков к элементам, необходимо чтобы эти элементы на странице были доступны. Определить, когда они будут доступны с момента загрузки документам можно с помощью события DOMContentLoaded
. Данное событие возникает на document
когда DOM полностью построено:
document.addEventListener('DOMContentLoaded', function () {
// DOM полностью построен и доступен
...
});
Задачи
1. Скрыть элемент по нажатию кнопки с классом spoiler-trigger
Написать JavaScript код, который при нажатии на кнопку spoiler-trigger
будет скрывать элемент, расположенный сразу за ней. При этом на странице таких кнопок может быть несколько.

<style>
.hide {
display: none;
}
</style>
<button class="spoiler-trigger">Скрыть/показать контент</button>
<div>...</div>
...
<button class="spoiler-trigger">Скрыть/показать контент</button>
<div>...</div>
Решение
2. Создать выпадающее меню
Имеется следующая разметка (стили добавлять не нужно, они имеются в примере):
<div class="dropdown">
<button class="dropdown__trigger">Меню</button>
<div class="dropdown__content">
<a href="#">Ссылка 1</a>
<a href="#">Ссылка 2</a>
<a href="#">Ссылка 3</a>
</div>
</div>

Необходимо написать скрипт, который будет при нажатии на кнопку (.dropdown__trigger
) переключался класс show
у элемента .dropdown
:
