提问者:小点点

Laravel Livewire导线:单击“创建无限循环”


我有一个Livewire组件,这是一个产品过滤器。这些查询都运行良好,但有时会产生无限的请求循环。

你可以在下面的GIF中看到这种情况,这是Laravel Debugbar的捕获。我单击了一些过滤器,然后突然它进入了这个请求循环。

我特别使用wire:loading.attr=禁用在视图中的过滤器上,所以当请求仍在处理时,某人不能选择过滤器。

我的代码和一些背景:

Livewire组件

use App\Models\Product;
use App\Models\Brand;
use App\Models\Color;

class SearchProducts extends Component
{
    public ?array $brand = [];
    public ?array $color = [];

    protected $queryString = ['brand', 'color'];

    public function render()
    {
        $products = Product::query();

        $products = $products->with('brand');
        $products = $products->with('colors');

        $products = $this->filterBrands($products);
        $products = $this->filterColors($products);

        $products = $products->paginate(24);

        return view('livewire.search-products', [
            'all_brands' => Brand::where('status', 'active')->get(),
            'all_colors' => Color::where('status', 'active')->get(),
        ])->extends('app');
    }

    public function filterBrands($query)
    {
        $queryFilterBrand = array_filter($this->brand);
        
        return empty($queryFilterBrand) ? $query : $query->whereIn('brand_id', $queryFilterBrand);
    }

    public function filterColors($query)
    {
        $queryFilterColor = array_filter($this->color);

        return empty($queryFilterColor) ? $query : $query->whereHas('colors', function ($q) use ($queryFilterColor) {
            $q->whereIn('color_id', $queryFilterColor);
        });
    }

}

我使用array\u filter的原因是,如果我取消选择颜色值并在键中使用字符(wire:model=“brand.b{$brand-

Livewire的观点和问题

这很好:

@foreach($all_brands as $brand)
    <input type="checkbox" value="{{ $brand->id }}" id="brand.{{ $brand->id }}" wire:model="brand.{{ $brand->id }}" wire:loading.attr="disabled">
    <label class="search-label search-wide-label mb-2" for="brand.{{ $brand->id }}">{{ $brand->title }} <i class="fal fa-times float-right selected-icon"></i></label>
@endforeach

但当我选择两种或更多颜色之后,或者选择一种颜色然后取消选择时,这会创建一个无限循环。因此,问题似乎发生在第二次交互之后:

@foreach($all_colors as $color)
    <input type="checkbox" value="{{ $color->id }}" id="color.{{ $color->id }}" wire:model="color.{{ $color->id }}" wire:loading.attr="disabled">
    <label class="search-label search-wide-label mb-2" for="color.{{ $color->id }}">{{ $color->title }} <i class="fal fa-times float-right selected-icon"></i></label>
@endforeach

这很奇怪,因为这个边栏选项卡片段与上面所示的$brand完全相同:

唯一不同的是,颜色关系是品牌之间的关系。

我现在想这就是问题所在。。。

我尝试过但没有成功的事情

  • 删除$all_colors@foreach循环,只需将过滤器放入纯HTML(以检查问题是否与循环相关)
  • 添加wire:key=“brand.{{$brand-

控制台错误

最后一点,只有当无限循环发生时,我才在控制台中得到这个错误,所以它很可能是因果关系。

TypeError:null不是对象(计算'directive.value.split')

未处理的promise拒绝:TypeError:null不是对象(计算'directive.value.split')

都在加载状态中。js,我认为这是一个Livewire Javascript文件。

错误似乎发生在这里:

function startLoading(els) {
    els.forEach(({ el, directive }) => {
        if (directive.modifiers.includes('class')) {
            let classes = directive.value.split(' ').filter(Boolean)

共3个答案

匿名用户

回答了GitHub问题,复制到这里让其他人能够找到。

这是一个变形问题。

触发错误和循环的代码是wire:加载标题行和产品行。

原因是,当您选择两种或多种颜色时,不会显示结果。接下来发生的是,您将从显示标题/产品/总计切换到显示空状态。

但默认情况下,mordom并不知道应该删除旧div并添加新div。取而代之的是,它正试图将旧的第一个部门“改造”成新的部门。这意味着线:加载监听器在不应该被注册的时候仍然被注册。因此,为什么错误和循环。

不过,这是一个简单的解决方案。您需要将线键添加到定义它们的div中,以便morphdom知道它们实际上已完全更改,并删除旧键并添加新键。

看看下面的差异截图,了解我是如何让它工作的。我为这个文件中的所有顶级div添加了一个线键。

无论何时,我们都建议使用这样的条件来为条件中处于第一级的任何元素添加wire: key,这样变形就知道发生了变化。VueJS也有同样的问题,在循环中需要密钥。

diff的截图

匿名用户

因此,如果您在像这样的Foreach循环中使用wire: Model,您必须这样写:wire: Model="brand。{{$brand-

最新消息

无限循环由此解决,但现在发生的是,一旦选中复选框并再次单击以取消选中,数组值将设置为零,而不是从数组中删除。因此,其中将查找值为0的品牌ID,该ID不会返回结果。

更新2

循环实际上没有解决。。。见原问题。因为浪费了太多的时间和咖啡,所以给了这个$%$奖金。

匿名用户

我看到了几个问题:

您的

此外,您在输入元素上使用相同的name。这将导致复选框的问题,因为传递到后端的值具有相同的名称,我相信livewire将尝试基于此进行同步。将输入中的name字段更改为唯一可能是答案。