You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Livewire中过滤器组件与表格组件的通信及查询优化实现方案

方案1:先优化现有查询逻辑,避免堆砌在render方法

你可以把查询逻辑抽成独立的组件属性方法,或者下沉到模型的查询作用域中,彻底简化render方法:

  • 第一步:在现有Livewire组件中新增查询属性方法
// 把所有过滤查询逻辑抽成独立计算属性
public function getStationsProperty()
{
    return Station::query()
        ->when($this->byCpm, fn($query) => $query->where('CPM', $this->byCpm))
        ->when($this->byStartDay, fn($query) => $query->where('StartDay', $this->byStartDay))
        ->when($this->byEndDay, fn($query) => $query->where('EndDay', $this->byEndDay))
        ->when($this->byStartTime, fn($query) => $query->where('StartTime', $this->byStartTime))
        ->when($this->byEndTime, fn($query) => $query->where('EndTime', $this->byEndTime))
        ->when($this->byOwner, fn($query) => $query->where('owner_id', $this->byOwner))
        ->when($this->byFormat, fn($query) => $query->where('format_id', $this->byFormat))
        ->when($this->byMarketCity, fn($query) => $query->where('market_city_id', $this->byMarketCity))
        ->when($this->byMarketState, fn($query) => $query->where('market_state_id', $this->byMarketState))
        ->when($this->minCPM, fn($query) => $query->where('CPM', '>=', $this->minCPM.'%'))
        ->when($this->maxCPM, fn($query) => $query->where('CPM', '<=', $this->maxCPM.'%'))
        ->search($this->search)
        ->orderBy($this->sortBy, $this->sortDirection)
        ->paginate($this->perPage);
}
  • 第二步:简化render方法为以下代码即可
public function render()
{
    return view('livewire.workbooks-table', [
        'stations' => $this->stations,
    ]);
}

如果需要更高的复用性,可以把所有过滤逻辑下沉到Station模型的查询作用域中:

// Station模型中新增filter作用域
public function scopeFilter($query, array $filters)
{
    return $query
        ->when($filters['byCpm'] ?? null, fn($q) => $q->where('CPM', $filters['byCpm']))
        ->when($filters['byStartDay'] ?? null, fn($q) => $q->where('StartDay', $filters['byStartDay']))
        // 剩余所有过滤条件依次按上面的格式补充即可
        ->when($filters['maxCPM'] ?? null, fn($q) => $q->where('CPM', '<=', $filters['maxCPM'].'%'));
}

之后组件里的计算属性可以进一步简化为:

public function getStationsProperty()
{
    return Station::filter([
        'byCpm' => $this->byCpm,
        'byStartDay' => $this->byStartDay,
        // 传入所有过滤参数
        'maxCPM' => $this->maxCPM,
    ])
    ->search($this->search)
    ->orderBy($this->sortBy, $this->sortDirection)
    ->paginate($this->perPage);
}

方案2:拆分过滤器和表格为独立组件,通过Livewire事件通信
  • 第一步:创建独立的过滤器组件WorkbooksFilter,把所有过滤相关的属性、视图都移到该组件中,新增参数更新时的事件派发逻辑:
// WorkbooksFilter组件代码
public $byFormat, $byCpm, $byStartDay; // 所有过滤参数都移到这里

// 监听任意参数更新,向表格组件派发过滤事件
public function updated($propertyName)
{
    $this->dispatch('filters-updated', filters: [
        'byFormat' => $this->byFormat,
        'byCpm' => $this->byCpm,
        // 所有其他过滤参数都打包传入
    ])->to(WorkbooksTable::class);
}

过滤器的视图代码不需要改动,还是保留你原来的wire:model绑定即可。

  • 第二步:改造表格组件WorkbooksTable,监听过滤器派发的事件,接收参数执行查询:
// WorkbooksTable组件代码
public array $filters = []; // 存储接收的过滤参数

// Livewire3用注解监听事件,Livewire2用protected $listeners = ['filters-updated' => 'updateFilters']
#[On('filters-updated')]
public function updateFilters($filters)
{
    $this->filters = $filters;
    // 可选:参数更新后自动重置分页到第一页
    $this->resetPage();
}

public function getStationsProperty()
{
    // 直接用刚才下沉到模型的filter作用域接收参数查询
    return Station::filter($this->filters)
        ->search($this->search)
        ->orderBy($this->sortBy, $this->sortDirection)
        ->paginate($this->perPage);
}

public function render()
{
    return view('livewire.workbooks-table', [
        'stations' => $this->stations,
    ]);
}
  • 第三步:在父视图中同时引入两个组件即可
<div>
    <livewire:workbooks-filter />
    <livewire:workbooks-table />
</div>

内容的提问来源于stack exchange,提问作者Alexandra Claudia

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.10 23:33:03