Learning Book

Модель событий: всплытие и захват

Модель событий

addEventListener

const btn = document.querySelector('button')

// Базовый синтаксис
btn.addEventListener('click', function(event) {
  console.log('Клик!', event)
})

// Стрелочная функция
btn.addEventListener('click', (e) => {
  console.log(e.type)    // 'click'
  console.log(e.target)  // элемент, на который кликнули
})

// Удаление обработчика (нужна ссылка на ту же функцию!)
function handler(e) { console.log('клик') }
btn.addEventListener('click', handler)
btn.removeEventListener('click', handler)

Event объект

document.addEventListener('click', (event) => {
  // Тип события
  event.type           // 'click'

  // Элементы
  event.target         // элемент, на который кликнули
  event.currentTarget  // элемент, к которому привязан обработчик

  // Координаты (для мышиных событий)
  event.clientX        // X от viewport
  event.clientY        // Y от viewport
  event.pageX          // X от начала страницы
  event.pageY          // Y от начала страницы

  // Клавиши (для клавиатурных событий)
  event.key            // 'Enter', 'ArrowLeft', 'a'
  event.code           // 'KeyA', 'ArrowLeft'
  event.ctrlKey        // boolean
  event.shiftKey       // boolean
  event.altKey         // boolean

  // Управление
  event.preventDefault()         // отменить дефолтное действие
  event.stopPropagation()        // остановить всплытие
  event.stopImmediatePropagation() // остановить + другие обработчики на том же элементе
})

Bubbling и Capturing

Большинство событий проходят три фазы:

1. Capturing (перехват): document → body → parent → target
2. Target: обработчики на target элементе
3. Bubbling (всплытие): target → parent → body → document
// По умолчанию: обработчик в фазе bubbling
document.querySelector('.parent').addEventListener('click', (e) => {
  console.log('Bubbling — родитель')
})

// Третий параметр true / { capture: true } — фаза capturing
document.querySelector('.parent').addEventListener('click', (e) => {
  console.log('Capturing — родитель')
}, true)

// Порядок для клика на дочернем элементе:
// Capturing родитель → Handler дочернего → Bubbling родитель
Bubbling — событие "всплывает" от дочернего к родительскому. Capturing — "тонет" от корня к цели. Большинство событий bubbable. Исключения: focus, blur, mouseenter, mouseleave.
const btn = document.querySelector('button')

btn.addEventListener('click', (e) => {
  console.log('Обработчик 1')
  e.stopImmediatePropagation() // остановить ВСЕ обработчики на этом элементе
})

btn.addEventListener('click', (e) => {
  console.log('Обработчик 2') // НЕ ВЫПОЛНИТСЯ
})

document.addEventListener('click', () => {
  console.log('Документ') // НЕ ВЫПОЛНИТСЯ (всплытие остановлено)
})

// btn.addEventListener('click', e => e.stopPropagation())
// — остановит всплытие, но второй обработчик на btn всё равно выполнится

stopPropagation — останавливает всплытие, но другие обработчики на этом же элементе продолжают работать. stopImmediatePropagation — останавливает всё.