В архитектуре современных веб-приложений взаимодействие между компонентами часто становится узким местом. Для управления событиями и передачи данных между разными частями приложения используются паттерны Медиатор и Event Bus. Preact, как легковесная альтернатива React, не накладывает строгих правил, позволяя гибко интегрировать эти подходы.
Медиатор служит централизованным объектом, через который компоненты обмениваются информацией. Он помогает снизить связанность между компонентами и упрощает поддержку крупного приложения.
Централизация взаимодействий Все компоненты отправляют и получают сообщения через медиатор, что устраняет прямые зависимости между ними.
Слабая связанность Компоненты не знают о существовании друг друга. Они взаимодействуют только с медиатором.
Управление событиями Медиатор управляет подпиской и обработкой событий, обеспечивая упорядоченность и предсказуемость работы.
class Mediator {
constructor() {
this.channels = {};
}
subscribe(channel, fn) {
if (!this.channels[channel]) {
this.channels[channel] = [];
}
this.channels[channel].push(fn);
}
unsubscribe(channel, fn) {
if (!this.channels[channel]) return;
this.channels[channel] = this.channels[channel].filter(subscriber => subscriber !== fn);
}
publish(channel, data) {
if (!this.channels[channel]) return;
this.channels[channel].forEach(subscriber => subscriber(data));
}
}
export const mediator = new Mediator();
В Preact использование медиатора происходит через вызовы методов
publish и subscribe. Например, один компонент
может отправить событие о новом элементе:
import { mediator } from './mediator';
function AddItemButton() {
const handleClick = () => {
mediator.publish('itemAdded', { id: Date.now(), name: 'Новый элемент' });
};
return <button onCl ick={handleClick}>Добавить элемент</button>;
}
Другой компонент подписывается на событие:
import { useEffect, useState } from 'preact/hooks';
import { mediator } from './mediator';
function ItemList() {
const [items, setItems] = useState([]);
useEffect(() => {
const handleNewItem = (item) => setItems(prev => [...prev, item]);
mediator.subscribe('itemAdded', handleNewItem);
return () => mediator.unsubscribe('itemAdded', handleNewItem);
}, []);
return (
<ul>
{items.map(item => <li key={item.id}>{item.name}</li>)}
</ul>
);
}
Event Bus — это вариация медиатора, ориентированная на события. Он часто используется для глобального обмена событиями без необходимости передачи их через пропсы.
Глобальность События доступны в любой части приложения, что упрощает коммуникацию между разнородными компонентами.
Производительность Event Bus минимизирует лишние перерендеры, так как обработка событий происходит вне дерева компонентов.
Поддержка асинхронных операций Event Bus удобно использовать для уведомлений об успешных действиях, ошибок или обновлений состояния.
import { EventEmitter } from 'events';
export const eventBus = new EventEmitter();
Подписка на событие:
import { useEffect, useState } from 'preact/hooks';
import { eventBus } from './eventBus';
function NotificationList() {
const [notifications, setNotifications] = useState([]);
useEffect(() => {
const handleNotification = (message) => setNotifications(prev => [...prev, message]);
eventBus.on('notify', handleNotification);
return () => eventBus.off('notify', handleNotification);
}, []);
return (
<ul>
{notifications.map((msg, idx) => <li key={idx}>{msg}</li>)}
</ul>
);
}
Отправка события:
import { eventBus } from './eventBus';
function NotifyButton() {
const notify = () => {
eventBus.emit('notify', 'Новое уведомление');
};
return <button onCl ick={notify}>Уведомить</button>;
}
| Характеристика | Медиатор | Event Bus |
|---|---|---|
| Централизация | Высокая | Средняя |
| Слабая связанность | Да | Да |
| Глобальные события | Не обязательно | Да |
| Управление подписками | Через объект | Через события EventEmitter |
| Поддержка асинхронности | Реализуется вручную | Встроенная через emit/on |
useEffect и useState
позволяет управлять подписками на события с автоматическим снятием
слушателей при размонтировании компонентов.Эти подходы повышают масштабируемость приложения, делают архитектуру гибкой и позволяют строить чистую коммуникацию между компонентами без прямой зависимости.