我遇到了 Livewire 的wire:click 方法在 Alpine.js x-data 指令中不起作用的问题。这是我的设置的细分:
里面
routes/web.php
,
Route::get('/product/{slug}', [ProductController::class, 'show'])->name('product.show');
里面
app/Http/Controllers/ProductController.php
,
public function show($slug)
{
// Fetching the product and related products data
// Pass the product and related products to the view
return view('pages.products.show', compact('product', 'products'));
}
里面
resources/views/pages/products/show.blade.php
,
@extends('layouts.default')
@section('title', $product->model)
@section('content')
@livewire('button', ['product' => $product])
<div class="max-w-screen-xl mx-auto p-4">
@livewire('button', ['product' => $product])
<div x-data="{ mainImage: '{{ $product->images->first() ? asset('img/products/' . $product->slug . '/' . $product->images->first()->filename) : asset('img/common/img-unavailable.jpg') }}' }">
@livewire('button', ['product' => $product])
<div class="container mx-auto px-4 py-8">
@livewire('button', ['product' => $product])
</div>
</div>
@livewire('button', ['product' => $product])
<x-products.grid :products="$products" />
</div>
@endsection
里面
resources/views/livewire/button.blade.php
,
<div>
<button
class="bg-indigo-600 flex gap-2 items-center text-white px-6 py-2 rounded-md hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2" type="button" wire:click="clicked">
Add to Cart
</button>
</div>
里面
app/Livewire/Button.php
,
<?php
namespace App\Livewire;
use Barryvdh\Debugbar\Facades\Debugbar;
use Livewire\Component;
class Button extends Component
{
public $product;
public function mount($product)
{
$this->product = $product;
Debugbar::info("Product mounted:", $this->product);
}
public function render()
{
return view('livewire.button');
}
public function clicked()
{
Debugbar::info("clicked");
Debugbar::info("Product in cart:", $this->product);
// $this->emit('cartUpdated');
}
}
show.blade.php
视图中的所有 Livewire 按钮都可以正常工作,但 Alpine.js x-data
指令内的按钮除外。具体来说,该块内的按钮:
<div x-data="{ mainImage: '{{ $product->images->first() ? asset('img/products/' . $product->slug . '/' . $product->images->first()->filename) : asset('img/common/img-unavailable.jpg') }}' }">
@livewire('button', ['product' => $product])
<div class="container mx-auto px-4 py-8">
@livewire('button', ['product' => $product])
</div>
</div>
这些按钮上的
wire:click
方法不会触发 Livewire 组件中的 clicked
方法。但是,会调用 mount
方法,并将产品详细信息记录在 Debugbar 中。该 x-data
块之外的按钮按预期工作,单击它们会导致 AJAX 调用并记录“已单击”消息。
mount
方法并将产品数据正确传递到Livewire组件。wire:click
方法在 x-data
块之外有效。出现您面临的问题是因为当您尝试在 Alpine.js 上下文中触发 Livewire 操作时,Alpine.js 和 Livewire 并不总是无缝协作,尤其是当 Alpine 在 x-data 中管理 DOM 更新时指示。 Alpine.js 在 Livewire 处理之前拦截诸如wire:click之类的事件。
这里解决问题的方法:
解决方案 1:使用 x-on 进行 Livewire 活动
您可以使用Alpine的x-on指令来发出事件并触发Livewire方法,而不是直接使用wire:click。以下是调整按钮代码的方法:
<div x-data="{ mainImage: '{{ $product->images->first() ? asset('img/products/' . $product->slug . '/' . $product->images->first()->filename) : asset('img/common/img-unavailable.jpg') }}' }">
<button
class="bg-indigo-600 flex gap-2 items-center text-white px-6 py-2 rounded-md hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2"
type="button"
x-on:click="$wire.clicked"
>
Add to Cart
</button>
<div class="container mx-auto px-4 py-8">
<button
class="bg-indigo-600 flex gap-2 items-center text-white px-6 py-2 rounded-md hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2"
type="button"
x-on:click="$wire.clicked"
>
Add to Cart
</button>
</div>
在此解决方案中,Alpine.js 将在单击按钮时直接调用 $wire.clicked 方法,从而绕过 x-data 范围内的wire:click 的需要。