Події Livewire - це події браузера, тож їх бачать і Alpine, і будь-який JavaScript на сторінці.
З PHP у JavaScript. Подія, відправлена з компонента, доходить у браузер:
$this->dispatch('notify', message: 'Збережено', type: 'success');
{{-- Alpine-компонент сповіщень у макеті --}}
<div x-data="{ items: [] }"
x-on:notify.window="items.push($event.detail)">
...
</div>
// звичайний JavaScript
Livewire.on('notify', ({ message, type }) => showToast(message, type));
З JavaScript у Livewire. Компонент з #[On('cart-updated')] отримає подію, відправлену будь-звідки:
<button x-on:click="$dispatch('cart-updated', { count: 3 })">...</button>
Livewire.dispatch('cart-updated', { count: 3 });
Livewire.dispatchTo('cart-badge', 'cart-updated', { count: 3 });
У скрипті компонента (Livewire 4: тег <script> у шаблоні, this - це $wire):
<script>
this.$on('post-created', () => { /* ... */ });
this.$dispatchSelf('refresh');
</script>
Події браузера на корені компонента - wire:назва-події:
<div wire:custom-event="handle">
<button x-on:click="$dispatch('custom-event')">...</button> {{-- спливе до кореня --}}
</div>
<div wire:custom-event.window="handle"> {{-- подія з будь-якого місця сторінки --}}
Безпека - головне. Слухач #[On] - це метод, який будь-хто може викликати з консолі браузера з довільними параметрами: Livewire.dispatch('order-paid', { orderId: 5 }). Тож слухачі мають перевіряти права й дані так само, як дії. Подія order-paid, що сама по собі змінює статус замовлення, - діра.
Прибирання слухачів. Livewire.on() повертає функцію для відписки. В Alpine-компонентах, що живуть із wire:navigate, слухачі треба знімати в destroy(), інакше після кожного переходу вони накопичуватимуться:
Alpine.data('cartBadge', () => ({
off: null,
init() { this.off = Livewire.on('cart-updated', ({ count }) => (this.count = count)); },
destroy() { this.off?.(); },
}));
Трансляція з сервера (Echo) - слухачі виду #[On('echo:orders,OrderShipped')] отримують події WebSocket від Laravel Reverb чи Pusher без власного JavaScript.