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

Livewire 3分页异常:切换首页/第三、四页时功能失效

问题诊断与解决方案

核心问题分析

  1. 分页状态丢失:使用getPostsProperty计算属性处理分页查询时,每次访问都会重新生成分页实例,Livewire的WithPagination trait无法正确维护page状态,导致页码参数失效,出现数据显示异常。
  2. 重复wire:key引发渲染错误:两个模型的id可能重复,仅用$post->id作为wire:key会导致Livewire DOM对比逻辑混乱,引发数据渲染不全、分页按钮消失等问题。
  3. Union查询分页计数隐患:通过DB::raw包装Union查询时,需确保绑定参数正确传递,避免总记录数计算错误。

修正后的代码

1. ProfileFeed.php 组件文件

移除计算属性,将查询逻辑移至render方法,显式传递分页页码参数:

<?php
namespace App\Livewire;

use App\Models\LawPost;
use App\Models\QBankPost;
use Livewire\Component;
use Livewire\WithPagination;
use Illuminate\Support\Facades\DB;

class ProfileFeed extends Component
{
    use WithPagination;

    protected $paginationTheme = 'tailwind';

    public function render()
    {
        $qbankQuery = QBankPost::query()
            ->where('is_published', true)
            ->select('id', 'question as title', 'slug', 'answer as content', 'published_at', 'seo_image', 'label');

        $lawPosts = LawPost::query()
            ->where('is_published', true)
            ->select('id', 'title', 'slug', 'content', 'published_at', 'seo_image', 'label');

        $combinedQuery = $lawPosts->unionAll($qbankQuery);

        $posts = DB::table(DB::raw("({$combinedQuery->toSql()}) as combined"))
            ->mergeBindings($combinedQuery->getQuery())
            ->orderBy('published_at', 'desc')
            ->paginate(10, ['*'], 'page', $this->page);

        return view('livewire.profile-feed', [
            'posts' => $posts,
        ]);
    }
}

2. profile-feed.blade.php 视图文件

修改wire:key为唯一标识,避免重复冲突:

<div>
    @forelse ($posts as $post)
        <div wire:key="post-{{ $post->label }}-{{ $post->id }}">
            <article class="group grid rounded-sm grid-cols-1 md:grid-cols-8 overflow-hidden border border-neutral-300 bg-neutral-50 text-neutral-600 dark:border-neutral-700 dark:bg-neutral-900 dark:text-neutral-300 mb-5">
                <div class="flex items-center justify-center overflow-hidden mx-5 my-5">
                    <img src="{{ $post->seo_image ? asset($post->seo_image) : asset('images/' . $post->label . '/' . $post->slug . '.jpg') }}" class="h-52 md:h-full w-full object-cover transition duration-700 ease-out group-hover:scale-105" alt="{{  $post->title }}" />
                </div>
                <div class="flex flex-col justify-center p-6 col-span-5">

                    <a href="{{ route("{$post->label}.show", $post->slug) }}">
                        <h3 class="text-balance text-xl font-bold text-neutral-900 lg:text-2xl dark:text-white">{{ $post->title }}</h3>
                        <p class="my-4 max-w-lg text-pretty text-sm">
                            {!! Str::limit($post->content, 150) !!}
                        </p>
                        <span class="w-fit font-medium text-black underline-offset-2 hover:underline focus:underline focus:outline-hidden dark:text-white">
                            Published on: {{ \Carbon\Carbon::parse($post->published_at)->diffForHumans() }}
                        </span>
                    </a>
                </div>
            </article>
        </div>
    @empty
        No Post Found
    @endforelse

    <div class="mt-6">
        {{ $posts->links() }}
    </div>
</div>

额外处理方案(若总记录数仍异常)

如果Union查询的总记录数计算错误,可手动构造分页实例:

// 计算总记录数
$total = DB::table(DB::raw("({$combinedQuery->toSql()}) as combined"))
    ->mergeBindings($combinedQuery->getQuery())
    ->count();

// 手动创建分页实例
$posts = new \Illuminate\Pagination\LengthAwarePaginator(
    DB::table(DB::raw("({$combinedQuery->toSql()}) as combined"))
        ->mergeBindings($combinedQuery->getQuery())
        ->orderBy('published_at', 'desc')
        ->skip(($this->page - 1) * 10)
        ->take(10)
        ->get(),
    $total,
    10,
    $this->page,
    ['path' => \Illuminate\Pagination\Paginator::resolveCurrentPath()]
);

内容的提问来源于stack exchange,提问作者Siam Al Mahmud

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.14 18:44:51