分页
Laravel 的分页功能允许您查询数据子集,并让您的用户能够在这些结果的“页面”之间导航。
由于 Laravel 的分页器是为静态应用程序设计的,在非 Livewire 应用程序中,每次页面导航都会触发对包含所需页面(?page=2
)的新 URL 的完整浏览器访问。
但是,当您在 Livewire 组件中使用分页时,用户可以在保持在同一页面上的同时在页面之间导航。Livewire 将处理幕后的一切,包括使用当前页面更新 URL 查询字符串。
基本用法
下面是在 ShowPosts
组件中使用分页的最基本示例,一次仅显示十个帖子
WithPagination
特性
要利用 Livewire 的分页功能,每个包含分页的组件都必须使用 Livewire\WithPagination
特性。
<?php namespace App\Livewire; use Livewire\WithPagination;use Livewire\Component;use App\Models\Post; class ShowPosts extends Component{ use WithPagination; public function render() { return view('show-posts', [ 'posts' => Post::paginate(10), ]); }}
<div> <div> @foreach ($posts as $post) <!-- ... --> @endforeach </div> {{ $posts->links() }}</div>
正如您所看到的,除了通过 Post::paginate()
方法限制显示的帖子数量之外,我们还将使用 $posts->links()
呈现页面导航链接。
有关使用 Laravel 进行分页的更多信息,请查看 Laravel 的全面分页文档。
禁用 URL 查询字符串跟踪
默认情况下,Livewire 的分页器会像这样在浏览器 URL 的查询字符串中跟踪当前页面:?page=2
。
如果你希望继续使用 Livewire 的分页实用程序,但禁用查询字符串跟踪,可以使用 WithoutUrlPagination
特性来实现
use Livewire\WithoutUrlPagination;use Livewire\WithPagination;use Livewire\Component; class ShowPosts extends Component{ use WithPagination, WithoutUrlPagination; // ...}
现在,分页将按预期工作,但当前页面不会显示在查询字符串中。这也意味着当前页面不会在页面更改时保留。
自定义滚动行为
默认情况下,Livewire 的分页器会在每次页面更改后滚动到页面的顶部。
你可以通过将 false
传递给 links()
方法的 scrollTo
参数来禁用此行为,如下所示
{{ $posts->links(data: ['scrollTo' => false]) }}
或者,你可以向 scrollTo
参数提供任何 CSS 选择器,Livewire 将找到与该选择器匹配的最近元素,并在每次导航后滚动到该元素
{{ $posts->links(data: ['scrollTo' => '#paginated-posts']) }}
重置页面
在对结果进行排序或筛选时,通常希望将页码重置回 1
。
出于这个原因,Livewire 提供了 $this->resetPage()
方法,允许你从组件中的任何位置重置页码。
以下组件演示了在提交搜索表单后使用此方法重置页面
<?php namespace App\Livewire; use Livewire\WithPagination;use Livewire\Component;use App\Models\Post; class SearchPosts extends Component{ use WithPagination; public $query = ''; public function search() { $this->resetPage(); } public function render() { return view('show-posts', [ 'posts' => Post::where('title', 'like', '%'.$this->query.'%')->paginate(10), ]); }}
<div> <form wire:submit="search"> <input type="text" wire:model="query"> <button type="submit">Search posts</button> </form> <div> @foreach ($posts as $post) <!-- ... --> @endforeach </div> {{ $posts->links() }}</div>
现在,如果用户在结果的第 5
页,然后通过按“搜索帖子”进一步筛选结果,页面将重置回 1
。
可用的页面导航方法
除了 $this->resetPage()
之外,Livewire 还提供了其他有用的方法,用于从组件以编程方式在页面之间导航
方法 | 描述 |
---|---|
$this->setPage($page) |
将分页器设置为特定页码 |
$this->resetPage() |
将页面重置回 1 |
$this->nextPage() |
转到下一页 |
$this->previousPage() |
转到上一页 |
多个分页器
由于 Laravel 和 Livewire 都使用 URL 查询字符串参数来存储和跟踪当前页码,如果一个页面包含多个分页器,则为它们分配不同的名称非常重要。
为了更清楚地说明问题,请考虑以下 ShowClients
组件
use Livewire\WithPagination;use Livewire\Component;use App\Models\Client; class ShowClients extends Component{ use WithPagination; public function render() { return view('show-clients', [ 'clients' => Client::paginate(10), ]); }}
如你所见,上述组件包含一组分页的 clients。如果用户导航到此结果集的第 2
页,则 URL 可能如下所示
http://application.test/?page=2
假设该页面还包含一个 ShowInvoices
组件,该组件也使用分页。要独立跟踪每个分页器的当前页,你需要为第二个分页器指定一个名称,如下所示
use Livewire\WithPagination;use Livewire\Component;use App\Models\Invoices; class ShowInvoices extends Component{ use WithPagination; public function render() { return view('show-invoices', [ 'invoices' => Invoice::paginate(10, pageName: 'invoices-page'), ]); }}
现在,由于已将 pageName
参数添加到 paginate
方法,当用户访问 invoices 的第 2
页时,URL 将包含以下内容
https://application.test/customers?page=2&invoices-page=2
在命名分页器上使用 Livewire 的页面导航方法时,你必须提供页面名称作为附加参数
$this->setPage(2, pageName: 'invoices-page'); $this->resetPage(pageName: 'invoices-page'); $this->nextPage(pageName: 'invoices-page'); $this->previousPage(pageName: 'invoices-page');
连接到页面更新
Livewire 允许你在页面更新之前和之后执行代码,方法是在组件中定义以下方法中的任何一个
use Livewire\WithPagination; class ShowPosts extends Component{ use WithPagination; public function updatingPage($page) { // Runs before the page is updated for this component... } public function updatedPage($page) { // Runs after the page is updated for this component... } public function render() { return view('show-posts', [ 'posts' => Post::paginate(10), ]); }}
命名分页器钩子
前面的钩子仅适用于默认分页器。如果你使用的是命名分页器,则必须使用分页器的名称来定义方法。
例如,以下是名为 invoices-page
的分页器的钩子示例
public function updatingInvoicesPage($page){ //}
通用分页器钩子
如果你不想在钩子方法名称中引用分页器名称,则可以使用更通用的替代方法,只需将 $pageName
作为第二个参数接收给钩子方法即可
public function updatingPaginators($page, $pageName){ // Runs before the page is updated for this component...} public function updatedPaginators($page, $pageName){ // Runs after the page is updated for this component...}
使用简单主题
你可以使用 Laravel 的 simplePaginate()
方法代替 paginate()
以获得更高的速度和简洁性。
使用此方法对结果进行分页时,只会向用户显示下一页和上一页导航链接,而不是每个页码的单独链接
public function render(){ return view('show-posts', [ 'posts' => Post::simplePaginate(10), ]);}
有关简单分页的更多信息,请查看 Laravel 的“simplePaginator”文档。
使用游标分页
Livewire 也支持使用 Laravel 的游标分页,这是一种在大型数据集中有用的更快的分页方法
public function render(){ return view('show-posts', [ 'posts' => Post::cursorPaginate(10), ]);}
通过使用 cursorPaginate()
代替 paginate()
或 simplePaginate()
,应用程序 URL 中的查询字符串将存储一个编码的游标,而不是一个标准页码。例如
https://example.com/posts?cursor=eyJpZCI6MTUsIl9wb2ludHNUb05leHRJdGVtcyI6dHJ1ZX0
有关游标分页的更多信息,请查看 Laravel 的游标分页文档。
使用 Bootstrap 代替 Tailwind
如果你使用 Bootstrap 而不是 Tailwind 作为应用程序的 CSS 框架,你可以将 Livewire 配置为使用 Bootstrap 样式的分页视图,而不是默认的 Tailwind 视图。
要实现此目的,请在应用程序的 config/livewire.php
文件中设置 pagination_theme
配置值
'pagination_theme' => 'bootstrap',
在自定义分页主题之前,你必须先通过运行以下命令将 Livewire 的配置文件发布到应用程序的 /config
目录
php artisan livewire:publish --config
修改默认分页视图
如果你想修改 Livewire 的分页视图以适应应用程序的样式,你可以使用以下命令发布它们
php artisan livewire:publish --pagination
运行此命令后,以下四个文件将被插入到 resources/views/vendor/livewire
目录中
视图文件名 | 描述 |
---|---|
tailwind.blade.php |
标准的 Tailwind 分页主题 |
tailwind-simple.blade.php |
简单的 Tailwind 分页主题 |
bootstrap.blade.php |
标准的 Bootstrap 分页主题 |
bootstrap-simple.blade.php |
简单的 Bootstrap 分页主题 |
发布文件后,你可以完全控制它们。在模板中使用分页结果的 ->links()
方法渲染分页链接时,Livewire 将使用这些文件,而不是它自己的文件。
使用自定义分页视图
如果你希望完全绕过 Livewire 的分页视图,你可以通过以下两种方式渲染你自己的视图
- Blade 视图中的
->links()
方法 - 组件中的
paginationView()
方法
->links()
通过 第一种方法是直接将自定义分页 Blade 视图名称传递给 ->links()
方法
{{ $posts->links('custom-pagination-links') }}
渲染分页链接时,Livewire 现在将在 resources/views/custom-pagination-links.blade.php
中查找视图。
paginationView()
通过 第二种方法是在组件中声明一个 paginationView
方法,该方法返回你想要使用的视图的名称
public function paginationView(){ return 'custom-pagination-links-view';}
示例分页视图
下面是一个简单的 Livewire 分页视图的未设置样式示例,供你参考。
如你所见,你可以通过向按钮添加 wire:click="nextPage"
,直接在模板中使用 Livewire 的页面导航帮助程序,例如 $this->nextPage()
<div> @if ($paginator->hasPages()) <nav role="navigation" aria-label="Pagination Navigation"> <span> @if ($paginator->onFirstPage()) <span>Previous</span> @else <button wire:click="previousPage" wire:loading.attr="disabled" rel="prev">Previous</button> @endif </span> <span> @if ($paginator->onLastPage()) <span>Next</span> @else <button wire:click="nextPage" wire:loading.attr="disabled" rel="next">Next</button> @endif </span> </nav> @endif</div>