Пользовательские события в JavaScript: зачем нужны и как настроить
hard

Пользовательские события в JavaScript: зачем нужны и как настроить

Когда стандартных не хватает

Ключевую роль во взаимодействии пользователя с веб-страницей или веб-приложением на JavaScript играют события: их обработка обеспечивает интерактивность. И хотя в JS много встроенных стандартных событий, бывает, что нужно создать собственное для обработки какого-то сценария. Разбираемся, зачем нужны пользовательские события, как их создавать и настраивать.

События в JavaScript — это сигналы, что что-то произошло, и вызвать их могут действия пользователя или браузера, а также программный код. Вот несколько примеров: 

  • Мы наводим курсор на кнопку, и от этого она меняет цвет. 
  • Мы нажимаем на кнопку, и отображается скрытое содержимое.
  • Мы выбираем какой-то вариант в выпадающем списке, и появляется сообщение с выбранным значением.
  • Мы меняем размер окна браузера, и вёрстка страницы адаптируется под новый масштаб.

Таким образом события помогают создавать интерактивные и адаптивные веб-сайты и приложения, которые реагируют на действия пользователя и изменения на странице. По сути, использование веб-приложения или посещение и действия на веб-странице — это просто серия каких-то событий.

Зачем нужны пользовательские события

Основную пользу пользовательских событий мы уже упомянули: они позволяют создавать и обрабатывать события, которые не предусмотрены в JavaScript. Например, при разработке игры можно создать событие, которое будет каким-то образом обрабатывать повышение уровня игрока. Но есть и другие причины использовать пользовательские события.

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

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

Пользовательские события могут помочь облегчить взаимодействие между разными компонентами или разными частями приложения или сайта, позволяя им общаться через событийно-ориентированный подход. В больших приложениях, где компонентов множество, можно обеспечить гибкое и эффективное общение между компонентами без жёсткой привязки друг к другу.

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

Создание пользовательских событий с помощью Event

Простые пользовательские события можно создать с помощью конструктора Event. Этот способ подходит, если нам не нужно передавать вместе с событием дополнительные данные. Например, это может быть событие, которое сигнализирует о каком-то изменении статуса, но информация о самом статусе не требуется.

Стандартный синтаксис создания пользовательского события с помощью конструктора Event такой:

const meEvent = new Event('myEvent', {
  bubbles: true,
  cancelable: true,
  composed: false
})

Мы создали событие myEvent, передав имя события конструктору Event. Конструктор события также принимает объект, который определяет некоторые важные свойства события.

Свойство bubbles указывает, должно ли событие распространяться вверх к родительскому элементу. Значение true означает, что, если событие отправляется в дочернем элементе, родительский элемент может прослушивать событие и выполнять действие на его основе. Такое поведение характерно для большинства стандартных событий, но для пользовательских событий по умолчанию установлено значение false.

Свойство cancelable указывает, следует ли отменить событие. Стандартные события по умолчанию отменяются, поэтому вы можете вызывать их, что предотвратит действие события по умолчанию. Если для свойства пользовательского события cancelable установлено значение false, вызов не выполнит никаких действий.

Свойство composed определяет, должно ли событие переходить из теневого DOM в реальный. Если для bubbles установлено значение false, значение этого свойства не будет иметь значения, поскольку мы явно указываем событию не подниматься вверх. Но если мы хотим отправить пользовательское событие в веб-компоненте и прослушивать его в родительском элементе в реальном DOM, тогда для свойства compound необходимо установить значение true.

Создание пользовательских событий с помощью CustomEvent

Если нужно создать настраиваемое событие и передать с ним какие-то данные, вместо Event лучше использовать конструктор CustomEvent — у него больше гибкость и функциональность. Кроме того, CustomEvent поддерживается всеми современными браузерами и считается стандартным способом создания пользовательских событий.

Стандартный синтаксис такой:

const myEvent = new CustomEvent("myevent", {
  detail: {},
  bubbles: true,
  cancelable: true,
  composed: false,
});

Любые данные, которые необходимо передать прослушивателю, можно передать в свойстве detail, которое создаётся при инициализации события.

Настройка пользовательских событий

После создания события его можно отправить с помощью метода dispatchEvent() любому DOM-элементу. Это могут быть все элементы HTML, документ, окно и так далее. Делается это так:

// Отправляем пользовательское событие
document.dispatchEvent(customEvent);

Чтобы реагировать на пользовательские события, нам нужно добавить прослушиватели событий к целевым элементам. Прослушиватели событий «слушают» события определённого типа и выполняют функцию, когда это событие происходит.

// Добавляем прослушиватель события
document.addEventListener('customEventType', function(event) {
    // Добавляем логику обработки события
    console.log('Пользовательское событие инициировано данными:', event.detail);
});

Рассмотрим детальный пример создания и использования пользовательского события с помощью CustomEvent. Создадим пользовательское событие userLoggedIn, которое будет передавать данные о пользователе:

// Создание события с передачей данных
const userLoggedInEvent = new CustomEvent('userLoggedIn', {
  detail: { username: 'mpolyanin', timestamp: new Date() }
});

В объекте detail мы передали имя пользователя и текущую метку времени.

Теперь добавим обработчик для события userLoggedIn, который будет выполняться, когда это событие произойдёт:

// Элемент, к которому будет привязано событие
const element = document.getElementById('myElement');

// Добавляем обработчик события
element.addEventListener('userLoggedIn', function(e) {
  console.log('Авторизация пользователя:', e.detail.username);
  console.log('Временная отметка:', e.detail.timestamp);
});

Мы привязали обработчик события к элементу с идентификатором myElement. Когда событие userLoggedIn будет инициировано, обработчик выведет в консоль имя пользователя и метку времени.

Теперь нам нужно инициировать событие, чтобы оно действительно произошло:

// Функция, вызываемая при логине пользователя
function userLogin(username) {
  const event = new CustomEvent('userLoggedIn', {
    detail: { username: username, timestamp: new Date() }
  });
  element.dispatchEvent(event);
}

// Пример вызова функции, инициирующей событие
userLogin('mpolyanin');

В функции userLogin мы создаём новое событие userLoggedIn, передавая имя пользователя и текущую метку времени в detail. Затем инициализируем это событие на элементе.

Передача и обработка дополнительных данных

Конструктор CustomEvent позволяет передавать и обрабатывать дополнительные данные при создании и использовании пользовательских событий. За счёт этого можно более гибко и эффективно управлять взаимодействиями между компонентами.

Дополнительные данные передаются через свойство detail объекта CustomEvent. Это свойство может содержать любой объект с информацией, которую необходимо передать обработчику события, — от простых значений до сложных объектов.

Пример создания события с использованием detail:

const userDetails = {
  username: 'mpolyanin',
  age: 39,
  isAdmin: true
};

const userEvent = new CustomEvent('userDetailsEvent', {
  detail: userDetails
});

Пример передачи данных:

const myCustomEvent = new CustomEvent('myEvent', {
  detail: {
    username: 'mpolyanin',
    age: 39,
    isAdmin: true
  }
});

Когда событие инициируется, данные, переданные в detail, становятся доступными в обработчике события через объект события event.

Пример обработки данных:

// Элемент, к которому будет привязано событие
const element = document.getElementById('myElement');

// Добавление обработчика события
element.addEventListener('userDetailsEvent', function(e) {
  const details = e.detail;
  console.log('Данные пользователя:', details);
  console.log('Логин:', details.username);
  console.log('Возраст:', details.age);
  console.log('Является администратором:', details.isAdmin);
});

// Инициализация события
element.dispatchEvent(userEvent);

Добавляем обработчик клика для инициализации события:

loginButton.addEventListener('click', function() { 
  const event = createUserLoginEvent(mpolyanin', 39, true); 
  loginButton.dispatchEvent(event); });

Когда пользователь нажмёт на кнопку «Войти», будет вызвана функция createUserLoginEvent, создано и инициировано событие userLoggedIn, и данные о пользователе будут выведены в консоль.

Что дальше

Это базовые штуки. В следующий раз сделаем проект, в котором создадим и используем несколько пользовательских событий, чтобы потренироваться на практике.

Обложка:

Алексей Сухов

Корректор:

Ирина Михеева

Вёрстка:

Маша Климентьева

Соцсети:

Юлия Зубарева

Получите ИТ-профессию
В «Яндекс Практикуме» можно стать разработчиком, тестировщиком, аналитиком и менеджером цифровых продуктов. Первая часть обучения всегда бесплатная, чтобы попробовать и найти то, что вам по душе. Дальше — программы трудоустройства.
Получите ИТ-профессию Получите ИТ-профессию Получите ИТ-профессию Получите ИТ-профессию
Еще по теме
hard