addEventListener і removeEventListener
addEventListener() реєструє функцію-обробник, яку браузер викличе, коли на елементі станеться певна подія, а removeEventListener() знімає раніше зареєстрований обробник. Обидва методи доступні на будь-якому вузлі DOM, а також на window і document.
Теорія
TL;DR
addEventListener(type, listener, options)підписує функцію на подію.- На одну й ту саму подію можна навісити скільки завгодно слухачів.
- Обробник отримує об'єкт
eventз даними про подію:type,targetта інші. removeEventListener(type, listener, options)знімає підписку.- Зняти можна лише ту саму функцію, яку додавали: нова анонімна стрілка не підійде.
- Опції
{ once, capture, passive }керують поведінкою слухача.
Швидкий приклад
<button id="btn">Натисни</button>const btn = document.querySelector('#btn');
function handleClick() {
alert('Кнопку натиснуто!');
}
btn.addEventListener('click', handleClick);
// пізніше, коли реакція вже не потрібна
btn.removeEventListener('click', handleClick);Сигнатура addEventListener
element.addEventListener(type, listener, options);| Аргумент | Що означає |
|---|---|
type | рядок, назва події ('click', 'input', 'keydown' тощо) |
listener | функція, яка виконається під час події |
options (необов'язково) | об'єкт з додатковими налаштуваннями, наприклад { once: true } |
Після підписки обробник викликається щоразу, коли подія доходить до цього елемента. Головна перевага над старим onclick у тому, що слухачів може бути багато і вони не перетирають один одного.
Об'єкт event
Браузер передає обробнику об'єкт події з усією інформацією про те, що сталося:
btn.addEventListener('click', (event) => {
console.log(event.type); // "click"
console.log(event.target); // елемент, на який клікнули
});Опції слухача
btn.addEventListener('click', handler, {
once: true, // обробник спрацює лише один раз
capture: false, // слухати на фазі спливання, це значення за замовчуванням
passive: true, // повідомляє браузеру, що preventDefault не буде викликано
});once: true знімає слухача автоматично після першого спрацювання, тому окремий виклик removeEventListener уже не потрібен. passive: true дозволяє браузеру не чекати на обробник перед прокручуванням, що помітно покращує плавність на дотикових екранах.
Зняття обробника: та сама функція
element.removeEventListener(type, listener, options);Важливо: щоб зняти обробник, треба передати ту саму функцію, яку ви передавали в
addEventListener.
Неправильно:
btn.addEventListener('click', () => console.log('hi'));
btn.removeEventListener('click', () => console.log('hi')); // не спрацюєТут створюються дві різні анонімні функції, і браузер не розуміє, яку саме знімати.
Правильно:
function handleClick() {
console.log('hi');
}
btn.addEventListener('click', handleClick);
btn.removeEventListener('click', handleClick);Тепер зняття спрацює.
Приклад із практики та підсумок
function handleScroll() {
console.log('Прокручування!');
}
// починаємо слухати
window.addEventListener('scroll', handleScroll);
// через 3 секунди перестаємо слухати
setTimeout(() => {
window.removeEventListener('scroll', handleScroll);
console.log('Слухача знято!');
}, 3000);| Метод | Що робить | Особливості |
|---|---|---|
addEventListener() | додає обробник події | на одну подію можна навісити кілька слухачів |
removeEventListener() | знімає обробник | працює лише з тим самим об'єктом функції |
options | налаштування | { once, capture, passive } керують поведінкою слухача |
Типові помилки
- Передавати в
removeEventListenerнову анонімну функцію або новий результат.bind(this): посилання відрізняється, і слухач залишається висіти. - Забувати, що
captureмає збігатися: слухач, доданий з{ capture: true }, знімається лише з таким самимcapture. - Не знімати слухачі з
windowчиdocumentпід час знищення компонента, через що виникають витоки пам'яті. - Викликати
preventDefault()усередині слухача зpassive: true: браузер його проігнорує і виведе попередження в консоль. - Навішувати
addEventListenerу кожному перемальовуванні і накопичувати дублікати обробників.
Коротка відповідь
Для співбесідиКоротка відповідь допоможе вам впевнено відповідати на цю тему під час співбесіди.