DOM Advanced

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

Научиться создавать и отправлять собственные события через CustomEvent, передавая данные через detail и слушая их через addEventListener.

Продвинутый (Advanced)

Кратко

CustomEvent — собственный тип события, который вы создаёте. detail — произвольные данные, передаваемые с событием. dispatchEvent() отправляет событие на элемент. addEventListener() слушает его. Это позволяет компонентам общаться без прямых зависимостей.


Подробно

Создание: const event = new CustomEvent('user-login', { detail: { username: 'Анна', role: 'admin' } });

Отправка: document.dispatchEvent(event);

Прослушивание: document.addEventListener('user-login', (e) => { console.log('Вошёл:', e.detail.username); console.log('Роль:', e.detail.role); });

detail — произвольные данные (объект, массив, строка, число).

Пример: компонент модалки

class Modal { constructor(element) { this.element = element; this.element.addEventListener('close', () => { this.hide(); }); }

hide() { this.element.style.display = 'none'; // Уведомляем другие компоненты this.element.dispatchEvent(new CustomEvent('modal-closed', { detail: { modalId: this.element.id } })); } }

// Другой компонент реагирует document.addEventListener('modal-closed', (e) => { console.log(Модалка ${e.detail.modalId} закрыта); });

События на конкретном элементе (не document):

const button = document.querySelector('#myButton'); button.addEventListener('my-custom-event', handler); button.dispatchEvent(new CustomEvent('my-custom-event', { detail: 42 }));


Ментальная модель

CustomEvent — как внутренняя переговорная комната. Вы создаёте свою «тему разговора» (тип события), передаёте «досье» (detail), и отправляете его (dispatchEvent). Любой, кто «слушает эту частоту» (addEventListener), получит сообщение. Компоненты общаются, не зная друг о друге напрямую.


Примеры

**Самый простой:**

javascript
// Создаём и отправляем событие
const event = new CustomEvent('greet', {
  detail: { name: 'Мир' }
});

document.dispatchEvent(event);

// Слушаем
document.addEventListener('greet', (e) => {
  console.log(`Привет, ${e.detail.name}!`);
});
// Вывод: Привет, Мир!

Простейший custom event: создаём, отправляем, слушаем.

**Простой:**

javascript
// Компонент корзины
class Cart {
  constructor() {
    this.items = [];
  }

  addItem(item) {
    this.items.push(item);
    // Уведомляем UI
    document.dispatchEvent(new CustomEvent('cart-updated', {
      detail: { items: this.items, total: this.items.length }
    }));
  }
}

// UI реагирует
document.addEventListener('cart-updated', (e) => {
  document.querySelector('.cart-count').textContent = e.detail.total;
});

const cart = new Cart();
cart.addItem({ name: 'Товар 1' }); // UI обновляется автоматически

Real-world: компонент корзины уведомляет UI через custom events.

**Реальный пример:**

javascript
// Система уведомлений
class NotificationService {
  static notify(message, type = 'info') {
    document.dispatchEvent(new CustomEvent('notification', {
      detail: { message, type, timestamp: Date.now() }
    }));
  }
}

// Слушатели
document.addEventListener('notification', (e) => {
  const { message, type } = e.detail;
  console.log(`[${type.toUpperCase()}] ${message}`);
});

NotificationService.notify('Загрузка...', 'info');
NotificationService.notify('Ошибка!', 'error');

Сервис уведомлений: несколько компонентов могут отправлять и слушать.


Частые ошибки

**Неправильно:** Отправлять custom event без detail

**Почему:** detail не обязателен, но без него событие бесполезно — нет данных для передачи.

**Правильно:** Передавайте через detail только то, что нужно слушателям.

**Неправильно:** Думать, что custom events — это замена для callback

**Почему:** Custom events — для общения между отдалёнными компонентами. Прямые callback'и проще для простых случаев.

**Правильно:** Пользовательские события (custom events) — слабая связь (loosely coupled): отправитель не знает, кто слушает. Колбэки (callbacks) — прямая связь: вызывающий передаёт функцию напрямую.

**Неправильно:** Забывать, что dispatchEvent синхронный

**Почему:** dispatchEvent вызывает все listener'ы синхронно (в том же потоке).

**Правильно:** Custom events обрабатываются синхронно, как и встроенные.


Важно запомнить

  • new CustomEvent('type', { detail: data }) — создание
  • element.dispatchEvent(event) — отправка
  • element.addEventListener('type', handler) — прослушивание
  • e.detail — данные события
  • Custom events обрабатываются синхронно

Связь

Назад: Вы умеете слушать события (DA1-DA4). Теперь вы можете создавать собственные типы событий.

Вперёд: Следующий урок (DA6) — события мыши и Drag and Drop API.

Материалы курса DOM Advanced — PROlab Academy.