队列作业完成后如何刷新组件?
How to refresh the component after the queue job is finished?
我有一个 table products
和 job_statuses
使用这个 package: laravel-job-status
job_statuses
中有一个名为 status
的专栏,一旦队列作业完成,包就创建了这个专栏 finished
!
所以我在 products
table 中创建了一个名为 job_status_id
的列(与 job_statuses 的关系)只是为了保存产品中的工作状态 ID table 看看这个作业是不是完成了!
简单地说,我使用 Livewire
创建了一个组件,用于在作业完成刷新组件时仅刷新单个产品:
class ProductIndex extends Component
{
public $product;
public function mount($product)
{
$this->product = $product;
}
public function render()
{
return view('livewire.merchant.product.index');
}
}
内部 product-index
组件:
@if ($product->job_status->status == 'finished')
// show real image
@else
// show loader
@endif
我的blade:
@foreach ($products as $product)
<livewire:merchant.product.product-index :product="$product" :key="$product->id">
@endforeach
如果状态为完成,如何刷新产品组件?
您可以在组件中添加 event-listener,然后从页面上的任何位置触发事件 - 甚至从 JavaScript - 以刷新组件。
要添加侦听器以使组件自行刷新,只需将以下行添加到您的 ProductIndex
组件。
protected $listeners = ['refreshProducts' => '$refresh'];
Livewire 现在将侦听发出的任何 refreshProducts
事件,一旦发出,它将刷新该组件。
您还可以进一步自定义它,方法是将神奇的 $refresh
操作替换为可以向其传递参数的方法。如果将事件命名为与方法相同,则无需指定 key/value 对(事件名称为键,方法名称为值),仅值就足够了。这是一个例子,
protected $listeners = ['refreshProducts'];
// ...
public function refreshProducts($product_id = null)
{
// Refresh if the argument is NULL or is the product ID
if ($product_id === null || $product_id === $this->product->id) {
// Do something here that will refresh the event
}
}
在 Livewire 组件中,您可以使用
发出事件
$this->emit('refreshProducts');`
// or if you are passing arguments, as with the second example,
$this->emit('refreshProducts', $productID);
您还可以从 JavaScript 发出事件,方法是
<script>
Livewire.emit('refreshProducts')
</script>
如果你想让队列在事件完成后触发该事件,你需要实现一些东西来轮询服务器询问“作业是否完成”然后触发事件,或者您可以使用 Laravel Echo 作为 websocket。这将允许您触发和侦听来自 Livewire 生态系统外部的事件。
轮询
When you're polling, you don't have to emit an event for every update, as the component will refresh itself continuously .
轮询是持续更新 Livewire 组件的最简单方法,它不需要像 Laravel Echo 那样的任何 websockets 集成。这意味着每隔 X 秒(默认为 2 秒),您的组件将向您的服务器发出一个 AJAX 请求,以获取其最新数据,并 re-render 自身使用新数据。
这很容易通过使用 wire:poll
属性包装组件来实现 - 这是一个使用 5 秒的示例。
<div wire:poll.5s>
<!-- The rest of your view here -->
</div>
但是,这意味着该组件的所有实例都将 re-render 自身并向服务器发出它们自己的 AJAX 请求以获取最新数据。您可能想为所有项目制作一个“父”组件,从而只有 1 个单一组件 re-render.
广播和 Websockets
我假设您已经 installed Laravel Echo。现在——要实现广播这个功能,首先需要创建一个事件。 运行 命令
php artisan make:event ProductStatusUpdated
这将在您的 app\Events
文件夹中创建一个活动。根据需要自定义它。 运行命令后看起来像这样,
class ProductStatusUpdated
{
use Dispatchable, InteractsWithSockets, SerializesModels;
/**
* Create a new event instance.
*
* @return void
*/
public function __construct()
{
//
}
/**
* Get the channels the event should broadcast on.
*
* @return \Illuminate\Broadcasting\Channel|array
*/
public function broadcastOn()
{
return new PrivateChannel('channel-name');
}
}
我们可以将频道从 PrivateChannel('channel-name')
更改为 Channel('products')
,这样我们就可以在 Livewire 的 products 频道中收听它(您可以命名任何你想要的频道,你也可以收听私人事件 - 在 Livewire 文档中有相关文档,在这个答案的底部引用)。
所以这意味着 broadcastOn
看起来像这样
public function broadcastOn()
{
return new Channel('products');
}
接下来,在作业完成其工作并设置所有状态后,使用
从Laravel触发该事件
event(new \App\Events\ProductStatusUpdated);
现在我们需要更新 Livewire 组件中的侦听器,以便我们可以通过 Laravel Echo(而不是我们之前执行的 Livewire 事件)实际侦听该频道上的广播。
protected $listeners = ['echo:products,ProductStatusUpdated' => 'refreshProducts'];
大功告成!您现在正在使用 Laravel Echo 广播一个事件,Livewire 截获该事件,然后运行。侦听器现在是一个 key/value 对,其中值仍然是组件中的方法名称(如果您愿意,您仍然可以使用魔法操作 $refresh
代替),键是 channel,event
以 echo:
.
为前缀
资源:
我有一个 table products
和 job_statuses
使用这个 package: laravel-job-status
job_statuses
中有一个名为 status
的专栏,一旦队列作业完成,包就创建了这个专栏 finished
!
所以我在 products
table 中创建了一个名为 job_status_id
的列(与 job_statuses 的关系)只是为了保存产品中的工作状态 ID table 看看这个作业是不是完成了!
简单地说,我使用 Livewire
创建了一个组件,用于在作业完成刷新组件时仅刷新单个产品:
class ProductIndex extends Component
{
public $product;
public function mount($product)
{
$this->product = $product;
}
public function render()
{
return view('livewire.merchant.product.index');
}
}
内部 product-index
组件:
@if ($product->job_status->status == 'finished')
// show real image
@else
// show loader
@endif
我的blade:
@foreach ($products as $product)
<livewire:merchant.product.product-index :product="$product" :key="$product->id">
@endforeach
如果状态为完成,如何刷新产品组件?
您可以在组件中添加 event-listener,然后从页面上的任何位置触发事件 - 甚至从 JavaScript - 以刷新组件。
要添加侦听器以使组件自行刷新,只需将以下行添加到您的 ProductIndex
组件。
protected $listeners = ['refreshProducts' => '$refresh'];
Livewire 现在将侦听发出的任何 refreshProducts
事件,一旦发出,它将刷新该组件。
您还可以进一步自定义它,方法是将神奇的 $refresh
操作替换为可以向其传递参数的方法。如果将事件命名为与方法相同,则无需指定 key/value 对(事件名称为键,方法名称为值),仅值就足够了。这是一个例子,
protected $listeners = ['refreshProducts'];
// ...
public function refreshProducts($product_id = null)
{
// Refresh if the argument is NULL or is the product ID
if ($product_id === null || $product_id === $this->product->id) {
// Do something here that will refresh the event
}
}
在 Livewire 组件中,您可以使用
发出事件$this->emit('refreshProducts');`
// or if you are passing arguments, as with the second example,
$this->emit('refreshProducts', $productID);
您还可以从 JavaScript 发出事件,方法是
<script>
Livewire.emit('refreshProducts')
</script>
如果你想让队列在事件完成后触发该事件,你需要实现一些东西来轮询服务器询问“作业是否完成”然后触发事件,或者您可以使用 Laravel Echo 作为 websocket。这将允许您触发和侦听来自 Livewire 生态系统外部的事件。
轮询
When you're polling, you don't have to emit an event for every update, as the component will refresh itself continuously .
轮询是持续更新 Livewire 组件的最简单方法,它不需要像 Laravel Echo 那样的任何 websockets 集成。这意味着每隔 X 秒(默认为 2 秒),您的组件将向您的服务器发出一个 AJAX 请求,以获取其最新数据,并 re-render 自身使用新数据。
这很容易通过使用 wire:poll
属性包装组件来实现 - 这是一个使用 5 秒的示例。
<div wire:poll.5s>
<!-- The rest of your view here -->
</div>
但是,这意味着该组件的所有实例都将 re-render 自身并向服务器发出它们自己的 AJAX 请求以获取最新数据。您可能想为所有项目制作一个“父”组件,从而只有 1 个单一组件 re-render.
广播和 Websockets
我假设您已经 installed Laravel Echo。现在——要实现广播这个功能,首先需要创建一个事件。 运行 命令
php artisan make:event ProductStatusUpdated
这将在您的 app\Events
文件夹中创建一个活动。根据需要自定义它。 运行命令后看起来像这样,
class ProductStatusUpdated
{
use Dispatchable, InteractsWithSockets, SerializesModels;
/**
* Create a new event instance.
*
* @return void
*/
public function __construct()
{
//
}
/**
* Get the channels the event should broadcast on.
*
* @return \Illuminate\Broadcasting\Channel|array
*/
public function broadcastOn()
{
return new PrivateChannel('channel-name');
}
}
我们可以将频道从 PrivateChannel('channel-name')
更改为 Channel('products')
,这样我们就可以在 Livewire 的 products 频道中收听它(您可以命名任何你想要的频道,你也可以收听私人事件 - 在 Livewire 文档中有相关文档,在这个答案的底部引用)。
所以这意味着 broadcastOn
看起来像这样
public function broadcastOn()
{
return new Channel('products');
}
接下来,在作业完成其工作并设置所有状态后,使用
从Laravel触发该事件event(new \App\Events\ProductStatusUpdated);
现在我们需要更新 Livewire 组件中的侦听器,以便我们可以通过 Laravel Echo(而不是我们之前执行的 Livewire 事件)实际侦听该频道上的广播。
protected $listeners = ['echo:products,ProductStatusUpdated' => 'refreshProducts'];
大功告成!您现在正在使用 Laravel Echo 广播一个事件,Livewire 截获该事件,然后运行。侦听器现在是一个 key/value 对,其中值仍然是组件中的方法名称(如果您愿意,您仍然可以使用魔法操作 $refresh
代替),键是 channel,event
以 echo:
.
资源: