Кратко
СкопированоОбъект Event описывает событие, произошедшее на странице. Одной из причин возникновения событий являются действия пользователя, такие как клики мышкой Mouse или ввод с клавиатуры Keyboard. Существует множество различных событий с разным набором информации.
Пример
СкопированоСамый простой и широко распространённый способ использования событий — это отслеживание срабатывания кликов по каким-либо элементам на странице.
При подписке на событие мы передаём обработчик, который будет вызван при каждом срабатывании события в браузере. В случае, когда происходит событие типа click, обработчик будет вызван с событием Mouse:
element.addEventListener('click', function (event) { console.log(event)})
element.addEventListener('click', function (event) {
console.log(event)
})
Как пишется
СкопированоВ этом материале мы рассматриваем базовый объект события, каждое событие может содержать дополнительные свойства в зависимости от его типа, но список ниже есть у всех.
Свойства
Скопированоbubbles— является ли данное событие всплывающим.cancelable— является ли событие отменяемым.current— указывает на элемент, на котором установлен обработчик события.Target default— отменено ли поведение события по умолчанию.Prevented event— указывает на фазу срабатывания события.Phase is— указывает на происхождение события, будет в значенииTrusted true, если событие инициировано браузером, действиями пользователя или вызовами программных методов, напримерelement.. focus ( ) false— если событие инициировано с помощьюdispatch.Event ( ) target— ссылка на объект, которым было инициировано событие. Например, если событие произошло на поле ввода, мы получим ссылку на этот DOM элемент.time— время возникновения события в миллисекундах.Stamp type— тип события.
Методы
Скопированоcomposed— вернёт массив элементов, на которых сработает событие.Path ( ) prevent— предотвращает дефолтное поведение события. Если вызвать этот метод на событии клика по ссылке, то переход по ссылке не произойдёт, но событие продолжит распространение.Default ( ) stop— предотвращает распространение события.Propagation ( ) stop— делает то же самое, что иImmediate Propagation ( ) stop, но, в том числе, предотвращает вызов обработчиков события, которые были установлены на этом же элементе.Propagation
Как понять
СкопированоРабота JavaScript основана на событийной модели. Это значит, что для того, чтобы запустился какой-либо код, должно произойти событие. Даже код, который был написан в файле и не привязан к событию, будет обработан после события, которое сообщит браузеру, что код загружен.
Событие может быть создано по следующим причинам:
- действие пользователя;
- системное событие;
- событие, созданное программно.
Примеры
СкопированоСистемное событие
СкопированоСистемное событие инициируется DOM-окружением и является отражением какого-то события, произошедшего в операционной системе. Например, событие, что пользователь находится онлайн. То есть на наличие активного интернет-соединения.
Мы можем отслеживать состояние интернет-соединения и показывать сообщение, если оно пропало.
window.addEventListener('offline', function() { alert('Отсутствует подключение к интернету')})
window.addEventListener('offline', function() {
alert('Отсутствует подключение к интернету')
})
Программное событие
СкопированоСобытие может быть создано с помощью кода. Поле is в таком событии будет содержать значение 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 и current. Их отличие легко увидеть на примере.
Создадим кнопку, положим в неё текст, обёрнутый в тег <span>, и навесим обработчик событий на кнопку. При клике на кнопку можно заметить, что current всегда будет кнопкой, на которой обрабатывается событие. При этом 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)
})
current всегда будет элементом, к которому привязан обработчик. То есть элементом, на котором вызывался add.
target — это элемент, на котором произошло событие. Оно может не совпадать с current, потому что большинство событий всплывают.
На собеседовании
Скопировано отвечает
СкопированоВсплытие события (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 всплывает – распространяется от кнопки вверх по дереву пока не достигнет контейнера.
Рассмотрим другой пример. Обернём наш контейнер с кнопкой ещё одним элементом <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}`)
}
При клике на элемент срабатывает всплытие, и функция handle вызывается соответствующее количество раз.
- Клик на button:
Зарегистрировано событие на элементе BUTTON Зарегистрировано событие на элементе DIV Зарегистрировано событие на элементе BODY
- Клик на container:
Зарегистрировано событие на элементе DIV Зарегистрировано событие на элементе BODY
- Клик на body:
Зарегистрировано событие на элементе BODY
❓ Зачем это нужно
- Удобно использовать для делегирования событий: можно вешать один обработчик на контейнер, а не на каждую кнопку;
- Повышает производительность, т. к. можно использовать меньше обработчиков.
☝️ Для остановки всплытия нужно использовать event в функции-обработчике события.
<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}`)
}
Тогда при клике на нашу кнопку handle будет вызвана только один раз. В консоли браузера мы увидим:
Зарегистрировано событие на элементе BUTTON
Это означает, что дальнейшее всплытие было остановлено вызовом event.
отвечает
СкопированоМетоды event и event предназначены для решения похожих задач и часто используются вместе.
Метод event останавливает распространение события (event propagation). Распространение события включает стадию захвата и стадию всплытия. Например, рассмотрим обработку события на стадии захвата — при распространении события от родительских элементов к дочерним. Обработчик, объявленный в дочернем элементе, не будет вызван после выполнения stop в обработчике родительского элемента. При этом действие по умолчанию не отменится.
Метод event отменяет действие по умолчанию. Например, переход по ссылке при клике на элемент <a>. Само событие продолжает распространяться после выполнения prevent.
Рассмотрим пример. Есть простая форма:
<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'
}
При клике по чекбоксу изменится цвет подписи, а также появится рамка вокруг формы.
В данном случае действием по умолчанию будет переключение чекбокса. Чтобы отменить это поведение, добавим prevent в обработчик checkbox:
function checkboxClick(event) { checkbox.style.color = 'blue' event.preventDefault()}
function checkboxClick(event) {
checkbox.style.color = 'blue'
event.preventDefault()
}
Теперь, при клике, чекбокс не меняет значение, однако остальные действия по-прежнему происходят.
Чтобы остановить всплытие события, но позволить чекбоксу переключаться, заменим event на stop:
function checkboxClick(event) { checkbox.style.color = 'blue' event.stopPropagation()}
function checkboxClick(event) {
checkbox.style.color = 'blue'
event.stopPropagation()
}
Методы prevent и stop также можно использовать при обработке событий на стадии захвата.
Например, мы можем отменить действие по умолчанию, используя обработчик form. Для этого объявим его для срабатывания на стадии захвата:
// 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'
}
☝️ Обратите внимание, что checkbox выполняется, но сам чекбокс не переключается. Это действие уже отменено в функции form, которая теперь срабатывает раньше, чем событие достигнет чекбокса.
Если заменить prevent на stop, обработчик checkbox не выполнится, но действие по умолчанию произойдёт:
function formClick(event) { form.style.border = '1px solid black' event.stopPropagation()}
function formClick(event) {
form.style.border = '1px solid black'
event.stopPropagation()
}