Запропонувати правкуПокращити цю статтюДопрацюйте відповідь до «Метод event.stopPropagation()». Ваші зміни проходять модерацію перед публікацією.Потрібне підтвердженняКонтентЩо ви змінюєте🇺🇸EN🇺🇦UAПереглядЗаголовок (UA)Коротка відповідь (UA)**`event.stopPropagation()` зупиняє подальше поширення події деревом DOM: обробники на поточному елементі спрацюють, а батьківські елементи подію вже не отримають.** Метод керує лише маршрутом події: він не скасовує стандартну дію браузера (для цього є `preventDefault()`) і не глушить інші обробники на тому самому елементі (для цього є `stopImmediatePropagation()`). ```javascript child.addEventListener('click', (e) => { e.stopPropagation(); // батьківські обробники вже не спрацюють }); ``` **Ключове:** `stopPropagation()` вимикає поширення події, а не її стандартну дію.Показується над повною відповіддю для швидкого нагадування.Відповідь (UA)Зображення**`event.stopPropagation()` зупиняє подальше поширення події деревом DOM: подія відпрацює на тому елементі, де вона сталася, але вище, до батьківських вузлів, уже не підніметься.** Метод впливає тільки на маршрут події. Він не скасовує стандартну дію браузера і не заважає іншим обробникам на тому самому елементі. ## Теорія ### TL;DR - `stopPropagation()` обриває поширення події далі по дереву: і спливання (bubbling) вгору, і подальше занурення (capturing) вниз. - Обробники, навішані на той самий елемент, усе одно виконаються: метод зупиняє сусідів по дереву, а не сусідів по елементу. - Стандартну дію браузера (перехід за посиланням, відправку форми) він не скасовує, для цього є `preventDefault()`. - `stopImmediatePropagation()` жорсткіший: він зупиняє і поширення, і решту обробників на цьому ж елементі. - Зловживання методом тихо ламає делегування подій: батьківський обробник просто перестає отримувати кліки. ### Швидкий приклад ```javascript document.querySelector('.child').addEventListener('click', (event) => { console.log('child'); event.stopPropagation(); // зупиняємо спливання, батько нічого не побачить }); ``` ### Спливання подій за замовчуванням Більшість подій у DOM спливають: після обробки на цільовому елементі вони йдуть угору по ланцюжку предків. ```html <div class="parent"> <button class="child">Натисни</button> </div> ``` ```javascript document.querySelector('.parent').addEventListener('click', () => { console.log('Батько'); }); document.querySelector('.child').addEventListener('click', () => { console.log('Дитина'); }); ``` Клік по кнопці `.child` дасть у консолі: ```text Дитина Батько ``` Спочатку спрацював обробник на кнопці, а потім подія спливла вгору і викликала обробник батька. ### Що саме робить stopPropagation() Досить викликати метод в обробнику дитини: ```javascript document.querySelector('.child').addEventListener('click', (event) => { console.log('Дитина'); event.stopPropagation(); // зупиняємо спливання }); ``` Тепер клік по кнопці виводить лише: ```text Дитина ``` Подія не дійде до батька, вона «застрягне» на кнопці. Те саме працює на глибшій вкладеності: ```html <div id="outer"> <div id="inner"> <button id="btn">Click me</button> </div> </div> ``` ```javascript outer.addEventListener('click', () => console.log('outer')); inner.addEventListener('click', () => console.log('inner')); btn.addEventListener('click', (e) => { e.stopPropagation(); console.log('button'); }); ``` Клік по кнопці друкує лише `button`, а `inner` та `outer` події вже не отримають. ### Делегування: коли спливання заважає Якщо на батьківському елементі висить один спільний обробник (класичне делегування), інколи клік по вкладеній кнопці не повинен до нього доходити: ```html <ul id="list"> <li>Елемент 1 <button>Видалити</button></li> <li>Елемент 2 <button>Видалити</button></li> </ul> ``` ```javascript list.addEventListener('click', (e) => { if (e.target.tagName === 'LI') { console.log('Клік по пункту'); } }); document.querySelectorAll('button').forEach(btn => btn.addEventListener('click', (e) => { e.stopPropagation(); // щоб батько не отримав подію console.log('Видалення елемента'); }) ); ``` Результат: - клік по `<li>` виводить «Клік по пункту»; - клік по кнопці виводить «Видалення елемента», і подія не спливає до списку. ### Чого stopPropagation() не робить - **Не скасовує стандартну дію браузера.** Форма все одно відправиться, посилання все одно відкриється. Для цього потрібен `event.preventDefault()`. - **Не заважає іншим обробникам того самого елемента.** Якщо на кнопці висить три слухачі `click`, усі три виконаються у порядку додавання. ### stopImmediatePropagation() і підсумкова таблиця Є жорсткіший варіант: ```javascript event.stopImmediatePropagation(); ``` Він зупиняє все: і поширення події по дереву, і решту обробників на цьому ж елементі. Тобто повністю блокує подальшу обробку. | Метод | Що робить | Зупиняє спливання? | Зупиняє інші обробники на елементі? | | --- | --- | --- | --- | | `event.stopPropagation()` | Перериває поширення події далі по дереву | Так | Ні | | `event.stopImmediatePropagation()` | Повністю блокує подальшу обробку події | Так | Так | | `event.preventDefault()` | Скасовує стандартну дію браузера | Ні | Ні | > Коротка пам'ятка: > `stopPropagation()` це «не піднімайся вище», > `preventDefault()` це «не роби стандартну дію», > `stopImmediatePropagation()` це «зупини все, навіть сусідів». ### Типові помилки - **Плутати з `preventDefault()`.** Перший керує маршрутом події, другий, стандартною дією браузера. Щоб форма і не спливала, і не відправилась, потрібні обидва виклики. - **Ставити `stopPropagation()` про всяк випадок у кожному обробнику.** Це тихо ламає делегування подій і глобальні слухачі на `document`, наприклад закриття випадного меню по кліку поза ним. - **Очікувати, що метод вимкне інші обробники цього ж елемента.** Не вимкне, для цього є `stopImmediatePropagation()`. - **Забувати про фазу занурення.** Якщо слухач додано з `{ capture: true }`, виклик обірве подію ще до того, як вона дійде до цільового елемента. - **Писати `return false` замість виклику.** У звичайному DOM-обробнику це не робить нічого: така поведінка є лише в jQuery, де `return false` викликає обидва методи одразу.Для рев’юераПримітка для модератора (необов’язково)Бачить лише модератор. Прискорює рев’ю.