事件
Livewire 提供了一个强大的事件系统,您可以使用它在页面上的不同组件之间进行通信。因为它在底层使用浏览器事件,您还可以使用 Livewire 的事件系统与 Alpine 组件甚至纯香草 JavaScript 进行通信。
要触发事件,您可以在组件的任何位置使用 dispatch()
方法,并从页面上的任何其他组件侦听该事件。
分发事件
要从 Livewire 组件分发事件,您可以调用 dispatch()
方法,向其传递事件名称以及您要随事件一起发送的任何其他数据。
下面是一个从 CreatePost
组件分发 post-created
事件的示例
use Livewire\Component; class CreatePost extends Component{ public function save() { // ... $this->dispatch('post-created'); }}
在此示例中,当调用 dispatch()
方法时,将分发 post-created
事件,并且页面上正在侦听此事件的每个其他组件都将收到通知。
您可以通过将数据作为第二个参数传递给 dispatch()
方法来随事件传递其他数据
$this->dispatch('post-created', title: $post->title);
侦听事件
要在 Livewire 组件中侦听事件,请在希望在分派给定事件时调用的方法上方添加 #[On]
属性
确保导入所有属性类。例如,以下 #[On()]
属性需要以下导入 use Livewire\Attributes\On;
。
use Livewire\Component;use Livewire\Attributes\On; class Dashboard extends Component{ #[On('post-created')] public function updatePostList($title) { // ... }}
现在,当 post-created
事件从 CreatePost
分派时,将触发网络请求,并且将调用 updatePostList()
操作。
如你所见,随事件发送的其他数据将作为其第一个参数提供给操作。
侦听动态事件名称
有时,你可能希望在运行时使用组件中的数据动态生成事件侦听器名称。
例如,如果你想将事件侦听器限定为特定 Eloquent 模型,则可以将模型的 ID 追加到事件名称,如下所示
use Livewire\Component;use App\Models\Post;use Livewire\Attributes\On; class ShowPost extends Component{ public Post $post; #[On('post-updated.{post.id}')] public function refreshPost() { // ... }}
如果上述 $post
模型的 ID 为 3
,则 refreshPost()
方法将仅由名为 post-updated.3
的事件触发。
侦听来自特定子组件的事件
Livewire 允许你在 Blade 模板中直接侦听单个子组件上的事件,如下所示
<div> <livewire:edit-post @saved="$refresh"> <!-- ... --></div>
在上述情况下,如果 edit-post
子组件分派 saved
事件,则将调用父级的 $refresh
,并且父级将被刷新。
你可以传递任何方法(就像通常对 wire:click
所做的那样),而不仅仅是传递 $refresh
。以下是如何调用可能执行关闭模态对话框等操作的 close()
方法的示例
<livewire:edit-post @saved="close">
如果子级连同请求分派参数,例如 $this->dispatch('close', postId: 1)
,则可以使用以下语法将这些值转发给父级方法
<livewire:edit-post @saved="close($event.detail.postId)">
使用 JavaScript 与事件交互
当你从应用程序内的 JavaScript 与 Livewire 的事件系统进行交互时,Livewire 的事件系统将变得更加强大。这解锁了应用程序中任何其他 JavaScript 与页面上的 Livewire 组件进行通信的能力。
在组件脚本内部侦听事件
你可以轻松地从一个 @script
指令中侦听组件模板内部的 post-created
事件,如下所示
@script<script> $wire.on('post-created', () => { // });</script>@endscript
上面的代码段将侦听其注册组件内的 post-created
事件。如果组件不再位于页面上,则不再触发事件侦听器。
阅读有关在 Livewire 组件中使用 JavaScript 的更多信息 →
从组件脚本分派事件
此外,你可以从组件的 @script
中分派事件,如下所示
@script<script> $wire.dispatch('post-created');</script>@endscript
当运行上述 @script
时,post-created
事件将分派到其定义组件中。
若要仅将事件分派到脚本所在的组件,而不分派到页面上的其他组件(防止事件“冒泡”),你可以使用 dispatchSelf()
$wire.dispatchSelf('post-created');
你可以通过将对象作为第二个参数传递给 dispatch()
来向事件传递任何其他参数
@script<script> $wire.dispatch('post-created', { refreshPosts: true });</script>@endscript
你现在可以从 Livewire 类和其他 JavaScript 事件侦听器访问这些事件参数。
以下是在 Livewire 类中接收 refreshPosts
参数的示例
use Livewire\Attributes\On; // ... #[On('post-created')]public function handleNewPost($refreshPosts = false){ //}
你还可以从事件的 detail
属性中从 JavaScript 事件侦听器访问 refreshPosts
参数
@script<script> $wire.on('post-created', (event) => { let refreshPosts = event.detail.refreshPosts // ... });</script>@endscript
阅读有关在 Livewire 组件中使用 JavaScript 的更多信息 →
从全局 JavaScript 侦听 Livewire 事件
或者,你可以使用 Livewire.on
从应用程序中的任何脚本全局侦听 Livewire 事件
<script> document.addEventListener('livewire:init', () => { Livewire.on('post-created', (event) => { // }); });</script>
上面的代码段将侦听页面上任何组件分派的 post-created
事件。
如果你出于任何原因希望移除此事件侦听器,你可以使用返回的 cleanup
函数执行此操作
<script> document.addEventListener('livewire:init', () => { let cleanup = Livewire.on('post-created', (event) => { // }); // Calling "cleanup()" will un-register the above event listener... cleanup(); });</script>
Alpine 中的事件
由于 Livewire 事件本质上是普通的浏览器事件,因此你可以使用 Alpine 侦听它们,甚至分派它们。
在 Alpine 中侦听 Livewire 事件
例如,我们可以使用 Alpine 轻松侦听 post-created
事件
<div x-on:post-created="..."></div>
上述代码段将侦听分配了 x-on
指令的 HTML 元素的任何 Livewire 组件的 post-created
事件。
要侦听页面上任何 Livewire 组件的事件,可以将 .window
添加到侦听器
<div x-on:post-created.window="..."></div>
如果要访问随事件发送的其他数据,可以使用 $event.detail
<div x-on:post-created="notify('New post: ' + $event.detail.title)"></div>
Alpine 文档提供了有关 侦听事件 的更多信息。
从 Alpine 分派 Livewire 事件
从 Alpine 分派出的任何事件都可以被 Livewire 组件拦截。
例如,我们可以轻松地从 Alpine 分派 post-created
事件
<button @click="$dispatch('post-created')">...</button>
与 Livewire 的 dispatch()
方法类似,可以通过将数据作为方法的第二个参数传递,将其他数据与事件一起传递
<button @click="$dispatch('post-created', { title: 'Post Title' })">...</button>
要了解有关使用 Alpine 分派事件的更多信息,请参阅 Alpine 文档。
如果你正在使用事件从子组件调用父组件上的行为,则可以使用 Blade 模板中的 $parent
直接从子组件调用操作。例如
<button wire:click="$parent.showCreatePostForm()">Create Post</button>
直接分派到另一个组件
如果你想使用事件在页面上的两个组件之间直接通信,可以使用 dispatch()->to()
修饰符。
下面是 CreatePost
组件直接向 Dashboard
组件分派 post-created
事件的示例,跳过侦听该特定事件的任何其他组件
use Livewire\Component; class CreatePost extends Component{ public function save() { // ... $this->dispatch('post-created')->to(Dashboard::class); }}
向组件自身分发组件事件
使用 dispatch()->self()
修饰符,可以限制事件仅被触发它的组件拦截
use Livewire\Component; class CreatePost extends Component{ public function save() { // ... $this->dispatch('post-created')->self(); }}
从 Blade 模板分发事件
可以使用 $dispatch
JavaScript 函数直接从 Blade 模板分发事件。当希望从用户交互(如按钮点击)触发事件时,这非常有用
<button wire:click="$dispatch('show-post-modal', { id: {{ $post->id }} })"> EditPost</button>
在此示例中,当按钮被点击时,show-post-modal
事件将使用指定的数据分发。
如果希望直接向另一个组件分发事件,可以使用 $dispatchTo()
JavaScript 函数
<button wire:click="$dispatchTo('posts', 'show-post-modal', { id: {{ $post->id }} })"> EditPost</button>
在此示例中,当按钮被点击时,show-post-modal
事件将直接分发到 Posts
组件。
测试分发的事件
要测试组件分发的事件,请在 Livewire 测试中使用 assertDispatched()
方法。此方法检查在组件生命周期中是否分发了特定事件
<?php namespace Tests\Feature; use Illuminate\Foundation\Testing\RefreshDatabase;use App\Livewire\CreatePost;use Livewire\Livewire; class CreatePostTest extends TestCase{ use RefreshDatabase; /** @test */ public function it_dispatches_post_created_event() { Livewire::test(CreatePost::class) ->call('save') ->assertDispatched('post-created'); }}
在此示例中,测试确保在 CreatePost
组件上调用 save()
方法时,post-created
事件使用指定的数据分发。
测试事件侦听器
要测试事件侦听器,可以从测试环境分发事件,并断言预期操作已针对该事件执行
<?php namespace Tests\Feature; use Illuminate\Foundation\Testing\RefreshDatabase;use App\Livewire\Dashboard;use Livewire\Livewire; class DashboardTest extends TestCase{ use RefreshDatabase; /** @test */ public function it_updates_post_count_when_a_post_is_created() { Livewire::test(Dashboard::class) ->assertSee('Posts created: 0') ->dispatch('post-created') ->assertSee('Posts created: 1'); }}
在此示例中,测试分发 post-created
事件,然后检查 Dashboard
组件是否正确处理该事件并显示更新的计数。
使用 Laravel Echo 的实时事件
Livewire 与 Laravel Echo 很好的配对,使用 WebSocket 在网页上提供实时功能。
此功能假定您已安装 Laravel Echo,并且 window.Echo
对象在应用程序中全局可用。有关安装 Echo 的更多信息,请查看 Laravel Echo 文档。
侦听 Echo 事件
假设您在 Laravel 应用程序中有一个名为 OrderShipped
的事件
<?php namespace App\Events; use App\Models\Order;use Illuminate\Broadcasting\Channel;use Illuminate\Broadcasting\InteractsWithSockets;use Illuminate\Contracts\Broadcasting\ShouldBroadcast;use Illuminate\Foundation\Events\Dispatchable;use Illuminate\Queue\SerializesModels; class OrderShipped implements ShouldBroadcast{ use Dispatchable, InteractsWithSockets, SerializesModels; public Order $order; public function broadcastOn() { return new Channel('orders'); }}
您可以像这样从应用程序的另一部分分发此事件
use App\Events\OrderShipped; OrderShipped::dispatch();
如果您仅使用 Laravel Echo 在 JavaScript 中侦听此事件,它将类似于以下内容
Echo.channel('orders') .listen('OrderShipped', e => { console.log(e.order) })
假设您已安装并配置 Laravel Echo,则可以在 Livewire 组件内侦听此事件。
下面是一个 `OrderTracker` 组件的示例,它正在侦听 `OrderShipped` 事件,以便向用户显示新订单的视觉指示
<?php namespace App\Livewire; use Livewire\Attributes\On; use Livewire\Component; class OrderTracker extends Component{ public $showNewOrderNotification = false; #[On('echo:orders,OrderShipped')] public function notifyNewOrder() { $this->showNewOrderNotification = true; } // ...}
如果您有包含变量的 Echo 通道(例如订单 ID),则可以通过 `getListeners()` 方法而不是 `#[On]` 属性来定义侦听器
<?php namespace App\Livewire; use Livewire\Attributes\On; use Livewire\Component;use App\Models\Order; class OrderTracker extends Component{ public Order $order; public $showOrderShippedNotification = false; public function getListeners() { return [ "echo:orders.{$this->order->id},OrderShipped" => 'notifyShipped', ]; } public function notifyShipped() { $this->showOrderShippedNotification = true; } // ...}
或者,如果您愿意,可以使用动态事件名称语法
#[On('echo:orders.{order.id},OrderShipped')]public function notifyNewOrder(){ $this->showNewOrderNotification = true;}
如果您需要访问事件有效负载,可以通过传入的 `$event` 参数进行访问
#[On('echo:orders.{order.id},OrderShipped')]public function notifyNewOrder($event){ $order = Order::find($event['orderId']); //}
私有和临场频道
您还可以侦听广播到私有和临场频道的事件
在继续之前,请确保您已为广播频道定义了 身份验证回调。
<?php namespace App\Livewire; use Livewire\Component; class OrderTracker extends Component{ public $showNewOrderNotification = false; public function getListeners() { return [ // Public Channel "echo:orders,OrderShipped" => 'notifyNewOrder', // Private Channel "echo-private:orders,OrderShipped" => 'notifyNewOrder', // Presence Channel "echo-presence:orders,OrderShipped" => 'notifyNewOrder', "echo-presence:orders,here" => 'notifyNewOrder', "echo-presence:orders,joining" => 'notifyNewOrder', "echo-presence:orders,leaving" => 'notifyNewOrder', ]; } public function notifyNewOrder() { $this->showNewOrderNotification = true; }}