我有一张 table products
和 job_statuses
使用这个package: laravel-job-statusjob_statuses
中有一列调用status
包做了这个专栏finished
一旦队列作业完成!
所以我在 products
中创建了一个列名为 job_status_id
的表(与 job_statuses 的关系)只是将作业状态 id 保存在 products 表中,以查看此作业是否完成!
我只是使用 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
如果状态已完成,如何刷新产品组件?
最佳答案
您可以在组件中添加事件监听器,然后从页面上的任何位置(甚至从 JavaScript)触发事件以刷新组件。
要添加监听器以使组件自行刷新,只需将以下行添加到您的 ProductIndex
零件。
protected $listeners = ['refreshProducts' => '$refresh'];
Livewire 现在将监听任何 refreshProducts
发出的事件,一旦发出,它将刷新该组件。您还可以通过替换魔术
$refresh
来进一步自定义它。带有方法的操作,您可以将参数传递给该方法。如果将事件命名为与方法相同的名称,则无需指定键/值对(事件名称为键,方法名称为值),仅值就足够了。这是一个例子,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 请求,以获取其最新数据,并使用新数据重新呈现自己。
这很容易通过使用
wire:poll
包装组件来实现。属性 - 这是使用 5 秒的示例。<div wire:poll.5s>
<!-- The rest of your view here -->
</div>
但是,这意味着该组件的所有实例都将重新呈现自己并向服务器发出自己的 AJAX 请求以获取最新数据。您可能希望为所有项目创建一个“父”组件,从而仅重新渲染 1 个单一组件。广播和网络套接字
我假设你有 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 至Channel('products')
,这使我们可以在产品 channel 的 Livewire 中收听它(您可以随意命名 channel ,也可以收听私有(private)事件 - Livewire 文档中有相关文档,在此答案的底部引用) .这意味着
broadcastOn
看起来像这样public function broadcastOn()
{
return new Channel('products');
}
接下来,在作业完成工作并设置所有状态后,从 Laravel 触发该事件,使用event(new \App\Events\ProductStatusUpdated);
现在我们需要更新 Livewire 组件中的监听器,以便我们可以通过 Laravel Echo 实际监听该 channel 上的广播(而不是我们之前所做的 Livewire 事件)。protected $listeners = ['echo:products,ProductStatusUpdated' => 'refreshProducts'];
我们完成了!你现在使用 Laravel Echo 来广播一个事件,Livewire 拦截然后运行。监听器现在是一个键/值对,其中的值仍然是组件中的方法名称(如果您愿意,您仍然可以使用魔术操作 $refresh
代替),键是 channel,event
前缀为 echo:
.资源:
关于php - 队列作业完成后如何刷新组件?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64186425/