URL 查询参数

您是视觉学习者吗?
通过我们深入的屏幕录制掌握 Livewire
立即观看

Livewire 允许您将组件属性存储在 URL 的查询字符串中。例如,您可能希望组件中的 $search 属性包含在 URL 中:https://example.com/users?search=bob。这对于诸如筛选、排序和分页之类的操作特别有用,因为它允许用户共享和书签页面的特定状态。

基本用法

以下是 ShowUsers 组件,它允许您通过简单的文本输入按姓名搜索用户

<?php
 
namespace App\Livewire;
 
use Livewire\Attributes\Url;
use Livewire\Component;
use App\Models\User;
 
class ShowUsers extends Component
{
public $search = '';
 
public function render()
{
return view('livewire.show-users', [
'users' => User::search($this->search)->get(),
]);
}
}
<div>
<input type="text" wire:model.live="search">
 
<ul>
@foreach ($users as $user)
<li wire:key="{{ $user->id }}">{{ $user->name }}</li>
@endforeach
</ul>
</div>

如您所见,由于文本输入使用 wire:model.live="search",因此当用户在字段中键入时,将发送网络请求以更新 $search 属性并在页面上显示过滤后的用户集。

但是,如果访问者刷新页面,搜索值和结果将丢失。

为了跨页面加载保留搜索值,以便访问者可以刷新页面或共享 URL,我们可以通过在 $search 属性上方添加 #[Url] 属性来将搜索值存储在 URL 的查询字符串中,如下所示

<?php
 
namespace App\Livewire;
 
use Livewire\Attributes\Url;
use Livewire\Component;
use App\Models\User;
 
class ShowUsers extends Component
{
#[Url]
public $search = '';
 
public function render()
{
return view('livewire.show-users', [
'posts' => User::search($this->search)->get(),
]);
}
}

现在,如果用户在搜索字段中键入“bob”,浏览器中的 URL 栏将显示

https://example.com/users?search=bob

如果他们现在从新的浏览器窗口加载此 URL,“bob”将填入搜索字段,并且用户结果将相应地进行筛选。

从 URL 初始化属性

如您在前一个示例中所见,当属性使用 #[Url] 时,它不仅会将更新后的值存储在 URL 的查询字符串中,还会在页面加载时引用任何现有的查询字符串值。

例如,如果用户访问 URL https://example.com/users?search=bob,Livewire 会将 $search 的初始值设置为“bob”。

use Livewire\Attributes\Url;
use Livewire\Component;
 
class ShowUsers extends Component
{
#[Url]
public $search = ''; // Will be set to "bob"...
 
// ...
}

可空属性

默认情况下,如果页面加载带有空查询字符串项,如 ?search=,Livewire 会将该值视为一个空字符串。在许多情况下,这是预期的,但有时你希望 ?search= 被视为 null

在这些情况下,你可以使用一个可空类型提示,如下所示

use Livewire\Attributes\Url;
use Livewire\Component;
 
class ShowUsers extends Component
{
#[Url]
public ?string $search;
 
// ...
}

因为 ? 存在于上述类型提示中,Livewire 会看到 ?search= 并将 $search 设置为 null,而不是空字符串。

反过来也一样,如果你在应用程序中设置 $this->search = null,它将在查询字符串中表示为 ?search=

使用别名

Livewire 让你完全控制 URL 查询字符串中显示的名称。例如,你可能有一个 $search 属性,但希望混淆实际属性名称或将其缩短为 q

你可以通过向 #[Url] 属性提供 as 参数来指定一个查询字符串别名

use Livewire\Attributes\Url;
use Livewire\Component;
 
class ShowUsers extends Component
{
#[Url(as: 'q')]
public $search = '';
 
// ...
}

现在,当用户在搜索字段中输入“bob”时,URL 将显示:https://example.com/users?q=bob,而不是 ?search=bob

排除某些值

默认情况下,Livewire 仅在值从初始化时的值发生更改时才在查询字符串中放置一个项。大多数情况下,这是期望的行为,但是,在某些情况下,你可能希望对 Livewire 从查询字符串中排除哪些值有更多的控制。在这些情况下,你可以使用 except 参数。

例如,在下面的组件中,$search 的初始值在 mount() 中被修改。为了确保浏览器仅在 search 值为空字符串时从查询字符串中排除 searchexcept 参数已添加到 #[Url]

use Livewire\Attributes\Url;
use Livewire\Component;
 
class ShowUsers extends Component
{
#[Url(except: '')]
public $search = '';
 
public function mount() {
$this->search = auth()->user()->username;
}
 
// ...
}

如果没有上述示例中的 except,Livewire 会在 search 的值等于 auth()->user()->username 的初始值时从查询字符串中删除 search 项。相反,因为使用了 except: '',Livewire 会保留所有查询字符串值,除非 search 为空字符串。

在页面加载时显示

默认情况下,Livewire 仅在页面上的值发生更改后才会在查询字符串中显示值。例如,如果 $search 的默认值为一个空字符串:"",当实际搜索输入为空时,URL 中将不会出现任何值。

如果你希望 ?search 条目始终包含在查询字符串中,即使该值为空,你也可以向 #[Url] 属性提供 keep 参数

use Livewire\Attributes\Url;
use Livewire\Component;
 
class ShowUsers extends Component
{
#[Url(keep: true)]
public $search = '';
 
// ...
}

现在,当页面加载时,URL 将更改为以下内容:https://example.com/users?search=

存储在历史记录中

默认情况下,Livewire 使用 history.replaceState() 来修改 URL,而不是 history.pushState()。这意味着当 Livewire 更新查询字符串时,它会修改浏览器历史记录状态中的当前条目,而不是添加一个新条目。

因为 Livewire “替换” 了当前历史记录,所以按浏览器中的“后退”按钮将转到前一页,而不是前一个 ?search= 值。

若要强制 Livewire 在更新 URL 时使用 history.pushState,你可以向 #[Url] 属性提供 history 参数

use Livewire\Attributes\Url;
use Livewire\Component;
 
class ShowUsers extends Component
{
#[Url(history: true)]
public $search = '';
 
// ...
}

在上面的示例中,当用户将搜索值从 “bob” 更改为 “frank”,然后单击浏览器的后退按钮时,搜索值(和 URL)将被设置回 “bob”,而不是导航到之前访问的页面。

使用 queryString 方法

查询字符串也可以定义为组件上的方法。如果某些属性具有动态选项,这可能很有用。

use Livewire\Component;
 
class ShowUsers extends Component
{
// ...
 
protected function queryString()
{
return [
'search' => [
'as' => 'q',
],
];
}
}

特性钩子

Livewire 也为查询字符串提供 钩子

trait WithSorting
{
// ...
 
protected function queryStringWithSorting()
{
return [
'sortBy' => ['as' => 'sort'],
'sortDirection' => ['as' => 'direction'],
];
}
}