Пользовательские события CustomEvent

Источник: «Elevating User Experiences With Custom Events»
JavaScript CustomEvent расширяют функциональность встроенной системы событий. Проще говоря, они позволяют программистам создавать и обрабатывать события, уникальные для их приложения, и в этой статье мы расскажем о них всё.

Оглавление

Уже долгое время JavaScript является эффективным языком для создания динамичных и интерактивных веб-сайтов. В основе этой интерактивности лежит система событий, позволяющая разработчикам реагировать на действия пользователей и создавать отзывчивые пользовательские интерфейсы. Несмотря на то, что система событий Document Object Model (DOM), поставляемая в комплекте, достаточно надёжна, бывают ситуации, когда требуется более настраиваемое и модульное решение. Именно в таких случаях и пригодятся CustomEvent.

CustomEvent, в отличие от обычных событий, таких как click или submit, позволяют разработчикам создавать уникальные виды событий, открывая более адаптируемые каналы связи между различными компонентами. Это всё равно что дать вашему веб-приложению уникальный язык для общения и реагирования на конкретные действия, сделав его более приспособленным к вашим потребностям.

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

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

Определение CustomEvent

Конструктор CustomEvent — это ключевая функция, добавленная в современный JavaScript и являющаяся основой пользовательских событий. Этот конструктор позволяет разработчикам создавать события с заданным типом и дополнительными деталями.

// Создание пользовательского события
const customEvent = new CustomEvent('customEventType', {
detail: { key: 'value' },
bubbles: true, // Будет ли событие всплывать через DOM или нет
cancelable: true // Можно ли отменить событие или нет
});

Анатомия CustomEvent

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

Пошаговое руководство по созданию CustomEvent

  1. Создайте экземпляр CustomEvent и определите тип события: Используйте конструктор CustomEvent, чтобы создать новое пользовательское событие и указать тип события.

    const FirstCustomEvent = new CustomEvent('customEventType');
  2. Опциональные детали: Включите опциональные детали в свойство detail. Детали используются для передачи свойств или данных обработчику события.

    const FirstCustomEvent = new CustomEvent('customEventType', {
    detail: { key: 'value' }
    });
  3. Всплытие и Отмена: Установите свойства bubbles и cancelable в зависимости от конкретного случая использования.

    const FirstCustomEvent = new CustomEvent('customEventType', {
    detail: { message: 'Hello, Custom Event!' },
    bubbles: true,
    cancelable: true,
    });

Примеры использования различных вариантов событий

Давайте рассмотрим две наиболее важные опции событий в этом разделе: "Всплытие" и "Отменяемость". Разработчикам необходимо понимать, как эти параметры работают в различных ситуациях, чтобы улучшить отзывчивость и интерактивность своих приложений.

Всплытие: Если для параметра bubbles установлено значение true, событие будет всплывать по иерархии DOM. Процесс, известный как "всплытие/распространение событий" или "бабблинг", происходит, когда событие, вызванное на одном элементе, заставляет его родителей испытать то же событие, распространяясь вверх по дереву DOM. Если для параметра bubbles установлено значение false, событие не будет всплывать и будет обрабатываться только целевым элементом.

const bubbleEvent = new CustomEvent('bubbleEvent', { bubbles: true });

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

Отменяемое:

const cancelableEvent = new CustomEvent('cancelableEvent', { cancelable: true });

Если для параметра cancelable установлено значение true, событие можно отменить, вызвав метод event.preventDefault() в слушателе события. При этом действие события по умолчанию будет остановлено. Если для cancelable установлено значение false, событие не может быть отменено.

Преимущества CustomEvent

Давайте рассмотрим основные преимущества CustomEvent и узнаем, как они повышают общую производительность JavaScript проектов.

Обработка событий

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

Преимущества работы с CustomEvent в модульной архитектуре

Использование модульной архитектуры похоже на строительство из кирпичиков LEGO в контексте разработки JavaScript: каждый компонент имеет свою функцию и может быть легко добавлен или удалён. Одним из наиболее эффективных способов повышения модульности вашего программного обеспечения является использование пользовательских событий. Итак, давайте рассмотрим некоторые преимущества использования CustomEvent в модульном дизайне.

Метод использующий addEventListener

Метод addEventListener используется для обработки CustomEvent, позволяя компонентам прослушивать определённые события и предпринимать соответствующие действия. Использование addEventListener для пользовательских событий выгодно тем, что способствует модульности кода, позволяя нескольким независимым компонентам по-разному обрабатывать одно и то же событие. Это также позволяет использовать несколько слушателей для одного и того же события, облегчает делегирование событий, поддерживает согласованный API для обработки стандартных и пользовательских событий и обеспечивает совместимость в различных браузерах. Теперь давайте рассмотрим управление пользовательскими событиями:

// Обработка пользовательского события
document.getElementById('myElement').addEventListener('customEventType', function (event) {
console.log('Custom event received:', event.detail);
});

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

Давайте рассмотрим несколько примеров кода, демонстрирующих обработку событий.

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Custom Event Example</title>
</head>
<body>

<!-- Кнопка для запуска пользовательского события -->
<button id="triggerButton">Trigger Custom Event</button>

<script>
// Определяем пользовательское событие с названием 'customEvent'
const customEvent = new CustomEvent('customEvent', { detail: { message: 'Hello, Custom Event!' } });

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

// Добавляем к кнопке слушатель события click, для вызова пользовательского события
document.getElementById('triggerButton').addEventListener('click', function () {
// Отправка пользовательского события при нажатии на кнопку
document.dispatchEvent(customEvent);
});
</script>

</body>
</html>

В приведённом выше примере пользовательское событие с именем customEvent определяется с помощью конструктора new CustomEvent. Пользовательское событие включает дополнительные сведения, в частности сообщение в свойстве detail. С помощью addEventListener в документ добавляется слушатель события. Он прослушивает CustomEvent и регистрирует сообщение из деталей события, когда оно срабатывает. Другой слушатель событий добавляется к кнопке с идентификатором triggerButton. Он прослушивает событие click и, когда оно срабатывает, отправляет пользовательское событие. Таким образом, когда HTML файл открывается в браузере и кнопка нажимается, прикреплённый к кнопке слушатель события click отправляет пользовательское событие customEvent. Слушатель событий перехватывает зарегистрированное в документе пользовательское событие, в результате чего в консоль выводится сообщение: "Custom event handled: Hello, Custom Event!".

Диспетчеризация событий CustomEvent

Развёртывание этих событий на DOM компоненты будет следующим шагом после того, как мы научились создавать CustomEvent. Диспетчеризация событий подразумевает запуск или отправку сигналов в веб-приложении. Такой подход ценен для достижения модульности, сопровождаемости и событийно-ориентированной архитектуры, где компоненты реагируют на события, а не взаимодействуют напрямую. Диспетчеризация событий особенно полезна для обработки взаимодействия с пользователем и создания свободно связанных и многократно используемых компонентов в веб-разработке. Для выполнения этой процедуры используется метод dispatchEvent. Теперь давайте рассмотрим, как работает диспетчеризация CustomEvent:

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

В этом примере пользовательское событие customEvent диспетчеризуется на элементе с идентификатором myElement. Все слушатели событий, подключённые к этому элементу, реагируют на пользовательское событие.

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

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

See the Pen

Изначально на странице в выпадающем списке есть заполнитель. Нажатие на кнопку "Update Dropdown" запускает пользовательское событие, извлекает случайные страны из Restcountries API и обновляет выпадающий список названиями этих стран. При клике кнопка получает случайные страны из API, запускает пользовательское событие updateDropdown с полученными странами и отправляет его. Затем это событие перехватывается слушателем события handleDropdownUpdate, обновляющим выпадающий список новыми пунктами. Функция getRandomElements перемешивает массив и выбирает заданное количество случайных элементов. В консоль выводится сообщение, что содержимое выпадающего списка было обновлено.

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

See the Pen

В приведённом выше примере при отправке формы отображается загрузочный спиннер, пользовательское событие showLoadingSpinnerEvent запускает его, а после имитации асинхронной операции (представленной функцией setTimeout()) отправляется второе пользовательское событие asyncOperationCompleteEvent, скрывающее загрузочный спиннер и выводящее в консоль сообщение, свидетельствующее о завершении асинхронной операции. Примечание: Используя DOMContentLoaded, вы гарантируете, что JavaScript код будет выполняться в нужное время, избегая потенциальных проблем, которые могут возникнуть, если он будет запущен до полной загрузки документа.

Примеры использования и приложения

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

Коммуникация компонентов

Одним из основных вариантов использования пользовательских событий в JavaScript является облегчение взаимодействия между различными компонентами пользовательского интерфейса. Компоненты сложного веб-приложения с множеством взаимосвязанных аспектов часто должны взаимодействовать друг с другом или инициировать действия в ответ на ввод пользователя. Для этого пользовательские события предлагают простой и независимый метод.

Рассмотрим следующий сценарий: При нажатии на кнопку открывается модальное окно, и другие компоненты должны быть уведомлены об этом событии, чтобы изменить своё состояние или выполнить необходимые действия:

See the Pen

Изначально на странице отображается кнопка "Open Modal" и другие компоненты. При нажатии на кнопку "Open Modal" отправляется пользовательское событие modalOpenedEvent, уведомляющее другие компоненты, что модальное окно было открыто. Состояние других компонентов изменяется, когда они получают пользовательское событие. В этом примере текстовое содержимое компонентов component1 и component2 обновляется, чтобы указать, что модальное окно открыто. Нажатие на кнопку "Close Modal", скрывает модальное окно и не вызывает никаких дополнительных событий в этом примере.

Интеграция сторонних компонентов

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

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

See the Pen

В приведённом выше примере страница содержит поле ввода даты datePicker, инициализированное Flatpickr, небольшой библиотекой для выбора даты и времени. Когда пользователь выбирает дату в поле выбора даты, отправляется пользовательское событие selectedDateChangeEvent с деталями, включающими выбранную дату и временную метку. Другой компонент на странице otherComponent прослушивает пользовательское событие selectedDateChange. Получив это событие, он обновляет своё состояние, отображая выбранную дату и временную метку, когда событие произошло.

Изменения состояния приложения

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

Например, вы можете отправить пользовательское событие при входе пользователя в систему, чтобы сообщить другим компонентам об изменении статуса аутентификации:

See the Pen

В приведённом выше примере есть форма логина с полями ввода имени пользователя и пароля. Когда форма отправлена (нажата кнопка Login), отправляется пользовательское событие userLoginEvent. Пользовательское событие содержит детали о логине, включая имя пользователя и временную метку логина. Статус аутентификации authStatus обновляет имя пользователя и временную метку логина.

Лучшие практики

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

Соглашения по именованию

Очень важно давать пользовательским событиям осмысленные и наглядные имена, если вы хотите сохранить понятность и ясность всего вашего кода. Разработчикам — в том числе вам и вашей команде — проще понять цель и замысел каждого пользовательского события, если его названия ясны и понятны.

// Хорошо: Название, описывающее событие
const userLoginEvent = new CustomEvent('userLogin');

// Избегайте: Расплывчатые или неясные названия событий
const event123 = new CustomEvent('123');

В приведённом выше примере название userLoginEvent гораздо более описательно и чётко указывает на его цель по сравнению с невнятным event123.

Распространение событий

Понимание распространения событий очень важно при работе с CustomEvent. Если установить значение true при создании пользовательского события, свойство bubbles позволяет событию распространяться вверх по DOM. Рассмотрите последствия использования этого свойства в зависимости от конкретного случая использования.

// Создание пользовательского события с включённой функцией всплывания
const bubblingEvent = new CustomEvent('bubblingEvent', { bubbles: true });

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

Обработка множества типов событий

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

// Обработка событий пользовательского логина
document.addEventListener('userLogin', handleUserLogin);

// Обработка событий изменения даты
document.addEventListener('dateChange', handleDateChange);

function handleUserLogin(event) {
// Логика обработки событий пользовательского логина
console.log('User logged in:', event.detail.userId);
}

function handleDateChange(event) {
// Логика обработки событий изменения даты
console.log('Selected date changed:', event.detail.newDate);
}

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

Избегайте чрезмерного использования CustomEvent

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

// Вместо использования пользовательских событий просто вызовите функцию
function performAction() {
// Логика экшена
}

// Прямой вызов функции
performAction();

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

Документирование пользовательских событий

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

/**
* Пользовательское событие, указывающее на то, что пользователь вошёл в систему.
* @event userLogin
* @type {CustomEvent}
* @property {Object} detail - детали ассоциированные с событием.
* @property {number} detail.userId - ID вошедшего пользователя.
*/

const userLoginEvent = new CustomEvent('userLogin', { detail: { userId: 123 } });

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

Заключение

В целом, пользовательские события в JavaScript представляют собой универсальное решение для улучшения взаимодействия между различными компонентами веб-приложений. Они расширяют стандартную систему событий, позволяя разработчикам создавать и отправлять события, отвечающие конкретным потребностям. Конструктор CustomEvent в сочетании с лучшими практиками, такими как чёткие соглашения об именовании и продуманное распространение событий, способствует модульности, удобству обслуживания и повторному использованию кодовой базы.

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

Дополнительные материалы

Предыдущая Статья

TypeScript vs JavaScript — Детальное сравнение

Следующая Статья

Что такое htmx