Клавиша / esc

Объект события Event

Информация о событии, произошедшем на странице.

Время чтения: меньше 5 мин

Кратко

Скопировано

Объект Event описывает событие, произошедшее на странице. Одной из причин возникновения событий являются действия пользователя, такие как клики мышкой MouseEvent или ввод с клавиатуры KeyboardEvent. Существует множество различных событий с разным набором информации.

Пример

Скопировано

Самый простой и широко распространённый способ использования событий — это отслеживание срабатывания кликов по каким-либо элементам на странице.

При подписке на событие мы передаём обработчик, который будет вызван при каждом срабатывании события в браузере. В случае, когда происходит событие типа click, обработчик будет вызван с событием MouseEvent:

        
          
          element.addEventListener('click', function (event) {    console.log(event)})
          element.addEventListener('click', function (event) {
    console.log(event)
})

        
        
          
        
      

Как пишется

Скопировано

В этом материале мы рассматриваем базовый объект события, каждое событие может содержать дополнительные свойства в зависимости от его типа, но список ниже есть у всех.

Свойства

Скопировано
  • bubbles — является ли данное событие всплывающим.
  • cancelable — является ли событие отменяемым.
  • currentTarget — указывает на элемент, на котором установлен обработчик события.
  • defaultPrevented — отменено ли поведение события по умолчанию.
  • eventPhase — указывает на фазу срабатывания события.
  • isTrusted — указывает на происхождение события, будет в значении true, если событие инициировано браузером, действиями пользователя или вызовами программных методов, например element.focus(). false — если событие инициировано с помощью dispatchEvent().
  • target — ссылка на объект, которым было инициировано событие. Например, если событие произошло на поле ввода, мы получим ссылку на этот DOM элемент.
  • timeStamp — время возникновения события в миллисекундах.
  • type — тип события.

Методы

Скопировано
  • composedPath() — вернёт массив элементов, на которых сработает событие.
  • preventDefault() — предотвращает дефолтное поведение события. Если вызвать этот метод на событии клика по ссылке, то переход по ссылке не произойдёт, но событие продолжит распространение.
  • stopPropagation() — предотвращает распространение события.
  • stopImmediatePropagation() — делает то же самое, что и stopPropagation, но, в том числе, предотвращает вызов обработчиков события, которые были установлены на этом же элементе.

Как понять

Скопировано

Работа JavaScript основана на событийной модели. Это значит, что для того, чтобы запустился какой-либо код, должно произойти событие. Даже код, который был написан в файле и не привязан к событию, будет обработан после события, которое сообщит браузеру, что код загружен.

Событие может быть создано по следующим причинам:

  • действие пользователя;
  • системное событие;
  • событие, созданное программно.

Примеры

Скопировано

Системное событие

Скопировано

Системное событие инициируется DOM-окружением и является отражением какого-то события, произошедшего в операционной системе. Например, событие, что пользователь находится онлайн. То есть на наличие активного интернет-соединения.

Мы можем отслеживать состояние интернет-соединения и показывать сообщение, если оно пропало.

        
          
          window.addEventListener('offline', function() {  alert('Отсутствует подключение к интернету')})
          window.addEventListener('offline', function() {
  alert('Отсутствует подключение к интернету')
})

        
        
          
        
      

Программное событие

Скопировано

Событие может быть создано с помощью кода. Поле isTrusted в таком событии будет содержать значение false, а, значит, мы будем знать, что событие было вызвано не системно и не пользователем.

Создадим своё событие и вызовем его на window:

        
          
          const myEvent = new CustomEvent('my-event', {  detail: {    spicy: 123,  },})window.addEventListener('my-event', function(evt) {  console.log('В поле spicy:', evt.detail.spicy)})window.dispatchEvent(myEvent)
          const myEvent = new CustomEvent('my-event', {
  detail: {
    spicy: 123,
  },
})

window.addEventListener('my-event', function(evt) {
  console.log('В поле spicy:', evt.detail.spicy)
})

window.dispatchEvent(myEvent)

        
        
          
        
      

На практике

Скопировано

Павел Минеев советует

Скопировано

🛠 В событии есть два похожих поля: target и currentTarget. Их отличие легко увидеть на примере.

Создадим кнопку, положим в неё текст, обёрнутый в тег <span>, и навесим обработчик событий на кнопку. При клике на кнопку можно заметить, что currentTarget всегда будет кнопкой, на которой обрабатывается событие. При этом target будет меняться в зависимости от того, куда на кнопке мы кликнули — на span внутри кнопки или на неё саму.

        
          
          <button class="button" type="button">  <span>Моя кнопочка</span></button>
          <button class="button" type="button">
  <span>Моя кнопочка</span>
</button>

        
        
          
        
      
        
          
          document.querySelector('.button').addEventListener('click', function (event) {  console.log('Событие инициировано на', event.target)  console.log('Событие поймано на', event.currentTarget)})
          document.querySelector('.button')
.addEventListener('click', function (event) {
  console.log('Событие инициировано на', event.target)
  console.log('Событие поймано на', event.currentTarget)
})

        
        
          
        
      
Открыть демо в новой вкладке

currentTarget всегда будет элементом, к которому привязан обработчик. То есть элементом, на котором вызывался addEventListener().

target — это элемент, на котором произошло событие. Оно может не совпадать с currentTarget, потому что большинство событий всплывают.

На собеседовании

Скопировано
Задать вопрос в рубрику
🤚 Я знаю ответ

Скопировано

Всплытие события (event bubbling) — это механизм Событийной модели браузера, при котором событие, произошедшее на вложенном элементе, последовательно «поднимается» вверх по дереву DOM через его предков, пока не достигнет объекта document (а в конце — window).

В Событийной модели есть ещё и фаза захвата (capturing) — она предшествует всплытию и идёт в обратном направлении: сверху вниз, от window к целевому элементу. По умолчанию обработчики срабатывают именно на фазе всплытия, поэтому чаще всего говорят именно о ней.

Проще говоря: если кликнули на кнопку внутри <div>, сначала обработчик сработает на кнопке, затем на <div>, затем на <body>, и так далее (если на всех перечисленных элементах присутствует обработчик события click).

Рассмотрим пример. Наш контейнер с кнопкой:

        
          
          <div id="container">  <button>Нажми на меня</button></div>
          <div id="container">
  <button>Нажми на меня</button>
</div>

        
        
          
        
      

Добавим обработку клика по кнопке:

        
          
          const container = document.getElementById('container')container.addEventListener('click', containerClick)function containerClick(event) {  console.log(`Зарегистрировано событие на контейнере ${event.currentTarget.tagName}`)}
          const container = document.getElementById('container')

container.addEventListener('click', containerClick)

function containerClick(event) {
  console.log(`Зарегистрировано событие на контейнере ${event.currentTarget.tagName}`)
}

        
        
          
        
      

При клике по кнопке вызывается слушатель события, который был установлен на контейнере. Это происходит благодаря тому, что событие click всплывает - сначала вызывается слушатель на кнопке (но там слушателя нет), потом на контейнере (там слушатель есть, он вызывает console.log()).

Рассмотрим другой пример. Обернём наш контейнер с кнопкой ещё одним элементом <body>:

        
          
          <html>  <body>    <div id="container">      <button>Нажми на меня</button>    </div>  </body></html>
          <html>
  <body>
    <div id="container">
      <button>Нажми на меня</button>
    </div>
  </body>
</html>

        
        
          
        
      

Добавим обработку клика на все три элемента:

        
          
          const button = document.querySelector('button')const container = document.getElementById('container')const body = document.querySelector('body')button.addEventListener('click', handleClick)container.addEventListener('click', handleClick)body.addEventListener('click', handleClick)function handleClick(event) {  console.log(`Зарегистрировано событие на элементе ${event.currentTarget.tagName}`)}
          const button = document.querySelector('button')
const container = document.getElementById('container')
const body = document.querySelector('body')

button.addEventListener('click', handleClick)
container.addEventListener('click', handleClick)
body.addEventListener('click', handleClick)

function handleClick(event) {
  console.log(`Зарегистрировано событие на элементе ${event.currentTarget.tagName}`)
}

        
        
          
        
      

При клике на элемент срабатывает всплытие, и функция handleClick() вызывается соответствующее количество раз.

  1. Клик на button:
Зарегистрировано событие на элементе BUTTON
Зарегистрировано событие на элементе DIV
Зарегистрировано событие на элементе BODY
  1. Клик на container:
Зарегистрировано событие на элементе DIV
Зарегистрировано событие на элементе BODY
  1. Клик на body:
Зарегистрировано событие на элементе BODY

❓ Зачем это нужно

  • Удобно использовать для делегирования событий: можно вешать один обработчик на контейнер, а не на каждую кнопку;
  • Повышает производительность, т. к. можно использовать меньше обработчиков.

☝️ Для остановки всплытия нужно использовать event.stopPropagation() в функции-обработчике события.

        
          
          <html>  <body>    <div id="container">      <button>Нажми на меня</button>    </div>  </body></html>
          <html>
  <body>
    <div id="container">
      <button>Нажми на меня</button>
    </div>
  </body>
</html>

        
        
          
        
      
        
          
          const button = document.querySelector('button')const container = document.getElementById('container')const body = document.querySelector('body')button.addEventListener('click', handleClick)container.addEventListener('click', handleClick)body.addEventListener('click', handleClick)function handleClick(event) {  event.stopPropagation()  console.log(`Зарегистрировано событие на элементе ${event.currentTarget.tagName}`)}
          const button = document.querySelector('button')
const container = document.getElementById('container')
const body = document.querySelector('body')

button.addEventListener('click', handleClick)
container.addEventListener('click', handleClick)
body.addEventListener('click', handleClick)

function handleClick(event) {
  event.stopPropagation()
  console.log(`Зарегистрировано событие на элементе ${event.currentTarget.tagName}`)
}

        
        
          
        
      

Тогда при клике на нашу кнопку handleClick() будет вызвана только один раз. В консоли браузера мы увидим:

Зарегистрировано событие на элементе BUTTON

Это означает, что дальнейшее всплытие было остановлено вызовом event.stopPropagation().

🤚 Я знаю ответ

Viktar Nezhbart  отвечает

Скопировано

Методы event.preventDefault() и event.stopPropagation() предназначены для решения похожих задач и часто используются вместе.

Метод event.stopPropagation() останавливает распространение события (event propagation). Распространение события включает стадию захвата и стадию всплытия. Например, рассмотрим обработку события на стадии захвата — при распространении события от родительских элементов к дочерним. Обработчик, объявленный в дочернем элементе, не будет вызван после выполнения stopPropagation() в обработчике родительского элемента. При этом действие по умолчанию не отменится.

Метод event.preventDefault() отменяет действие по умолчанию. Например, переход по ссылке при клике на элемент <a>. Само событие продолжает распространяться после выполнения preventDefault().

Рассмотрим пример. Есть простая форма:

        
          
          <form>  <label for="id-checkbox">Это чекбокс:</label>  <input type="checkbox" id="id-checkbox"></form>
          <form>
  <label for="id-checkbox">Это чекбокс:</label>
  <input type="checkbox" id="id-checkbox">
</form>

        
        
          
        
      

Добавим обработку клика по форме и чекбоксу на стадии всплытия:

        
          
          const form = document.querySelector('form')const label = form.querySelector('label')const checkbox = form.querySelector('#id-checkbox')form.addEventListener('click', formClick)checkbox.addEventListener('click', checkboxClick)function formClick(event) {  form.style.border = '1px solid black'}function checkboxClick(event) {  checkbox.style.color = 'blue'}
          const form = document.querySelector('form')
const label = form.querySelector('label')
const checkbox = form.querySelector('#id-checkbox')

form.addEventListener('click', formClick)
checkbox.addEventListener('click', checkboxClick)

function formClick(event) {
  form.style.border = '1px solid black'
}

function checkboxClick(event) {
  checkbox.style.color = 'blue'
}

        
        
          
        
      

При клике по чекбоксу изменится цвет подписи, а также появится рамка вокруг формы.

В данном случае действием по умолчанию будет переключение чекбокса. Чтобы отменить это поведение, добавим preventDefault() в обработчик checkboxClick:

        
          
          function checkboxClick(event) {  checkbox.style.color = 'blue'  event.preventDefault()}
          function checkboxClick(event) {
  checkbox.style.color = 'blue'
  event.preventDefault()
}

        
        
          
        
      

Теперь, при клике, чекбокс не меняет значение, однако остальные действия по-прежнему происходят.

Чтобы остановить всплытие события, но позволить чекбоксу переключаться, заменим event.preventDefault() на stopPropagation():

        
          
          function checkboxClick(event) {  checkbox.style.color = 'blue'  event.stopPropagation()}
          function checkboxClick(event) {
  checkbox.style.color = 'blue'
  event.stopPropagation()
}

        
        
          
        
      

Методы preventDefault() и stopPropagation() также можно использовать при обработке событий на стадии захвата.

Например, мы можем отменить действие по умолчанию, используя обработчик formClick. Для этого объявим его для срабатывания на стадии захвата:

        
          
          // formClick будет работать на стадии захвата событияform.addEventListener('click', formClick, true)checkbox.addEventListener('click', checkboxClick)function formClick(event) {  form.style.border = '1px solid black'  event.preventDefault()}function checkboxClick(event) {  checkbox.style.color = 'blue'}
          // formClick будет работать на стадии захвата события
form.addEventListener('click', formClick, true)
checkbox.addEventListener('click', checkboxClick)

function formClick(event) {
  form.style.border = '1px solid black'
  event.preventDefault()
}

function checkboxClick(event) {
  checkbox.style.color = 'blue'
}

        
        
          
        
      

☝️ Обратите внимание, что checkboxClick() выполняется, но сам чекбокс не переключается. Это действие уже отменено в функции formClick(), которая теперь срабатывает раньше, чем событие достигнет чекбокса.

Если заменить preventDefault() на stopPropagation(), обработчик checkboxClick не выполнится, но действие по умолчанию произойдёт:

        
          
          function formClick(event) {  form.style.border = '1px solid black'  event.stopPropagation()}
          function formClick(event) {
  form.style.border = '1px solid black'
  event.stopPropagation()
}