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
相关产品推荐
相关产品推荐

