Введение в события браузера в JavaScript
Узнайте, как работают события браузера в JavaScript: три способа добавления обработчиков, addEventListener, объект события и примеры.
Освоение событий браузера в JavaScript
Событие браузера — это сигнал о том, что на странице что-то произошло: пользователь нажал кнопку, нажал клавишу, изображение завершило загрузку, окно было изменено в размере. Реагирование на эти сигналы превращает статический документ в интерактивное приложение.
В этом руководстве объясняется, что такое события, три способа их прослушивания (и какой из них предпочтительнее), что даёт объект события, как прекратить прослушивание, а также рассматриваются шесть запускаемых реальных примеров. Если вы только знакомитесь с языком, начните с введения в JavaScript.
Понимание событий браузера
Событие — это действие или происшествие, которое браузер обнаруживает и позволяет вашему коду на него реагировать. События делятся на две широкие группы:
- События, инициированные пользователем — нажатие кнопки мыши, ввод текста, перемещение указателя, отправка формы.
- Системные события — завершение загрузки страницы, ошибка загрузки изображения, окончание CSS-анимации, изменение размера окна.
Типы событий
Вот некоторые из наиболее распространённых событий, сгруппированных по категориям:
| Категория | События |
|---|---|
| Мышь | click, dblclick, mouseover, mouseout, mousedown, mouseup |
| Клавиатура | keydown, keyup (keypress устарел) |
| Форма | submit, change, input, focus, blur |
| Документ / окно | DOMContentLoaded, load, resize, scroll, beforeunload |
У каждой категории есть своя отдельная глава: см. события мыши, события клавиатуры, события отправки формы и события загрузки ресурсов.
Три способа добавить обработчики событий
Существует три способа реагировать на событие. Они перечислены от наименее гибкого к наиболее гибкому.
1. HTML-атрибут (onclick="...") — быстрый способ, но смешивает JavaScript с разметкой и допускает только один обработчик. Избегайте его в реальных проектах.
<button onclick="alert('Button clicked!')">Click Me!</button>2. Свойство DOM (element.onclick) — код остаётся в JavaScript, однако назначение нового обработчика перезаписывает предыдущий, поэтому по-прежнему допускается только один обработчик на событие.
<button id="myButton">Click Me!</button>document.getElementById('myButton').onclick = function () {
alert('Button clicked!');
};3. addEventListener (рекомендуется) — стандартный подход. Вы можете прикрепить несколько обработчиков для одного и того же события, управлять фазой захвата/всплытия и удалить обработчик позже.
<button id="myButton">Click Me!</button>document.getElementById('myButton').addEventListener('click', function () {
alert('Button clicked!');
});addEventListener предпочтителен, поскольку позволяет регистрировать несколько слушателей для одного события и даёт более тонкий контроль над обработкой событий — например, вызов event.stopPropagation() или event.preventDefault(). Также он принимает объект параметров: { once: true } запускает обработчик только один раз, а { capture: true } прослушивает на фазе захвата (см. всплытие и захват).
Удаление обработчика событий
Слушатель остаётся прикреплённым до тех пор, пока вы его не удалите (или элемент не будет удалён сборщиком мусора). Для удаления необходимо передать ту же ссылку на функцию, которую вы добавляли — встроенную анонимную функцию удалить невозможно, так как на неё нет ссылки.
function handleClick() {
console.log('clicked');
}
const btn = document.getElementById('myButton');
btn.addEventListener('click', handleClick);
// later — stops the handler from firing again
btn.removeEventListener('click', handleClick);Объект события
Когда срабатывает событие, браузер создаёт объект события, описывающий произошедшее, и передаёт его первым аргументом в ваш обработчик. Полезные свойства включают:
event.type— имя события, например"click".event.target— элемент, который непосредственно инициировал событие.event.currentTarget— элемент, к которому прикреплён слушатель (равенthisв обработчике с обычной функцией).event.preventDefault()— отменяет действие браузера по умолчанию (например, переход по ссылке).event.stopPropagation()— останавливает всплытие события к элементам-предкам.
<button id="myButton">Click Me!</button>
<div style="margin-top:10px;" id="eventInfo"></div>
<script>
document.getElementById('myButton').addEventListener('click', function(event) {
var eventInfo = 'Event Type: ' + event.type + '<br />Clicked Element: ' + event.target.tagName;
document.getElementById('eventInfo').innerHTML = eventInfo;
});
</script>Практические примеры обработки событий браузера
Рассмотрим несколько практических примеров, демонстрирующих обработку событий браузера в реальных сценариях.
Пример 1: Событие отправки формы
Обработка отправки формы для проверки введённых данных перед отправкой на сервер:
<form id="loginForm">
Username: <input type="text" name="username" required />
Password: <input type="password" name="password" required />
<button type="submit">Login</button>
</form>
<script>
document.getElementById('loginForm').addEventListener('submit', function(event) {
event.preventDefault(); // Prevent the form from submitting normally
if (this.username.value.length < 4 || this.password.value.length < 4) {
alert('Username and password must be at least 4 characters long.');
} else {
this.submit(); // Submit the form manually if validation passes
alert('successfully submitted');
}
});
</script>(Примечание: здесь вместо стрелочной функции используется обычная функция, чтобы сохранить контекст this, что позволяет this.username и this.password корректно ссылаться на элементы формы.)
Пример 2: Обработка событий наведения и ухода мыши
Изменение стиля кнопки при наведении на неё мыши и сброс при уходе мыши:
<button id="hoverButton">Hover Over Me!</button>
<script>
const button = document.getElementById('hoverButton');
button.addEventListener('mouseover', function() {
this.style.backgroundColor = 'green';
});
button.addEventListener('mouseleave', function() {
this.style.backgroundColor = '';
});
</script>Пример 3: События клавиатуры
Выполнение функции при нажатии клавиши Enter:
<input type="text" id="inputField" placeholder="Type something and press Enter" />
<script>
document.getElementById('inputField').addEventListener('keydown', function(event) {
if (event.key === 'Enter') {
alert('You pressed Enter!');
}
});
</script>Пример 4: Функциональность перетаскивания
Реализация перетаскивания для простого переноса изображения внутри веб-страницы:
<span>Drop image below</span>
<div id="dragArea" style="width: 300px; height: 300px; border: 2px dashed #ccc;">
</div>
<img id="draggableImage" src="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='150' height='150'%3E%3Crect width='150' height='150' fill='%234f46e5'/%3E%3Ctext x='75' y='80' fill='white' font-size='18' text-anchor='middle'%3EDrag me%3C/text%3E%3C/svg%3E" draggable="true" style="width: 150px; height: 150px;">
<script>
const dragArea = document.getElementById('dragArea');
const draggableImage = document.getElementById('draggableImage');
// Event listener for the drag start
draggableImage.addEventListener('dragstart', function(event) {
event.dataTransfer.setData("text/plain", event.target.id);
});
// Event listener for dragging over the drag area
dragArea.addEventListener('dragover', function(event) {
event.preventDefault(); // Necessary to allow the drop
});
// Event listener for drop
dragArea.addEventListener('drop', function(event) {
event.preventDefault(); // Prevent default behavior (like opening as link for some elements)
const data = event.dataTransfer.getData("text/plain");
const image = document.getElementById(data);
dragArea.appendChild(image);
});
</script>Пояснение:
- Начало перетаскивания: при начале перетаскивания изображения его идентификатор сохраняется в данных перетаскивания.
- Перетаскивание над областью: предотвращение действия по умолчанию необходимо для разрешения сброса.
- Сброс: при сбросе изображение перемещается в область сброса.
Пример 5: События начала и конца анимации
Использование CSS-анимаций и обработка их начала и конца с помощью JavaScript:
<div id="animateBox" style="width: 100px; height: 100px; background: red; position: relative; animation: moveBox 5s 2;"></div>
<div id="animationStatus"></div>
<style>
@keyframes moveBox {
0% { left: 0; }
50% { left: 200px; }
100% { left: 0; }
}
</style>
<script>
const box = document.getElementById('animateBox');
const statusDisplay = document.getElementById('animationStatus');
box.addEventListener('animationstart', function() {
statusDisplay.innerHTML = 'Animation started';
});
box.addEventListener('animationend', function() {
statusDisplay.innerHTML = 'Animation ended';
});
box.addEventListener('animationiteration', function() {
statusDisplay.innerHTML = 'Animation iteration';
});
</script>(Примечание: animationstart и связанные с ним события являются стандартными в современных браузерах. Старые версии Safari могут требовать вендорных префиксов, например -webkit-animationstart, однако для текущей разработки рекомендуются стандартные имена.)
Пояснение:
animationstartсрабатывает один раз при начале анимации.animationiterationсрабатывает в начале каждого повтора — полезно, когда анимация настроена на многократное воспроизведение.animationendсрабатывает один раз по завершении анимации. Блок#animationStatusобновляется при каждом событии, обеспечивая живую обратную связь на странице.
Пример 6: Пользовательские события
Создание и отправка пользовательских событий для обработки специфических для приложения сценариев:
<button id="customEventButton">Trigger Custom Event</button>
<script>
// Creating a custom event
const myEvent = new CustomEvent('myCustomEvent', {
detail: { message: 'Custom event triggered' }
});
// Event listener for custom event
document.addEventListener('myCustomEvent', function(event) {
alert('Event Message: ' + event.detail.message);
});
// Dispatch the custom event when button is clicked
document.getElementById('customEventButton').addEventListener('click', function() {
document.dispatchEvent(myEvent);
});
</script>Пояснение:
- Создание пользовательского события: определяет пользовательское событие с дополнительными данными (
detail, содержащий сообщение). - Обработка события: настраивает слушатель пользовательского события, отображающий предупреждение с сообщением из деталей события.
- Запуск события: запускает пользовательское событие при нажатии кнопки.
Рекомендации
- Предпочитайте
addEventListenerвстроенным атрибутамonclick— это разделяет поведение и разметку и поддерживает несколько обработчиков. - Используйте обычные функции, когда вам нужно
thisдля ссылки на элемент; используйте стрелочные функции, когда не нужно, и читайтеevent.currentTarget. - Удаляйте ненужные слушатели с помощью
removeEventListener(передавая ту же ссылку на функцию), чтобы избежать утечек памяти, особенно в одностраничных приложениях. - Прикрепляйте один слушатель к родительскому элементу вместо множества к каждому дочернему при обработке списков — этот приём называется делегированием событий и основан на всплытии событий.
- Ограничивайте частоту высокочастотных событий, таких как
scrollиresize, чтобы избежать выполнения ресурсоёмких операций при каждом срабатывании; см. оптимизацию производительности DOM.
Заключение
События браузера — это мост между действиями пользователя и реакцией вашего кода. Ключевые выводы: используйте addEventListener для гибкости, извлекайте нужные данные из объекта события, вызывайте preventDefault() или stopPropagation() при необходимости переопределить поведение по умолчанию и удаляйте ненужные слушатели.
Далее изучите отдельные главы о событиях мыши, событиях клавиатуры, обработке отправки форм и отправке пользовательских событий, чтобы создавать более насыщенные интерфейсы, управляемые событиями.