URL 查询参数
Livewire 允许你把组件属性存进 URL 的查询字符串。例如,你可能希望组件中的 $search 属性出现在 URL 里:https://example.com/users?search=bob。这对筛选、排序、分页等场景特别有用,因为用户可以分享和收藏页面的特定状态。
基本用法
下面是一个 show-users 组件,通过简单的文本输入按姓名搜索用户:
<?php // resources/views/components/⚡show-users.blade.php
use Livewire\Attributes\Computed;
use Livewire\Component;
use App\Models\User;
new class extends Component {
public $search = '';
#[Computed]
public function users()
{
return User::search($this->search)->get();
}
};<div>
<input type="text" wire:model.live="search">
<ul>
@foreach ($this->users as $user)
<li wire:key="{{ $user->id }}">{{ $user->name }}</li>
@endforeach
</ul>
</div>可以看到,由于文本输入使用了 wire:model.live="search",用户在输入时会发送网络请求来更新 $search 属性,并在页面上显示筛选后的用户列表。
不过,如果访问者刷新页面,搜索值和结果就会丢失。
为了在页面加载之间保留搜索值,让访问者可以刷新页面或分享 URL,可以在 $search 属性上方加上 #[Url] 属性,把搜索值存进 URL 的查询字符串,如下所示:
<?php // resources/views/components/⚡show-users.blade.php
use Livewire\Attributes\Computed;
use Livewire\Attributes\Url;
use Livewire\Component;
use App\Models\User;
new class extends Component {
#[Url] // [tl! highlight]
public $search = '';
#[Computed]
public function users()
{
return User::search($this->search)->get();
}
};现在,如果用户在搜索框中输入「bob」,浏览器地址栏会显示:
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; // [tl! highlight]
// ...
}由于上述类型提示中有 ?,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 只会在值相对于初始化时发生变化时,才把该项写入查询字符串。多数时候这是期望行为,但在某些场景下,你可能希望更精细地控制哪些值要从查询字符串中排除。这时可以使用 except 参数。
例如,在下面的组件中,$search 的初始值在 mount() 中被修改。为确保浏览器仅在 search 为空字符串时才从查询字符串中排除 search,已在 #[Url] 上添加了 except 参数:
use Livewire\Attributes\Url;
use Livewire\Component;
class ShowUsers extends Component
{
#[Url(except: '')]
public $search = '';
public function mount() {
$this->search = auth()->user()->username;
}
// ...
}若上例没有 except,只要 search 的值等于初始值 auth()->user()->username,Livewire 就会从查询字符串中移除 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',
],
];
}
}Trait 钩子
Livewire 也为查询字符串提供了钩子。
trait WithSorting
{
// ...
protected function queryStringWithSorting()
{
return [
'sortBy' => ['as' => 'sort'],
'sortDirection' => ['as' => 'direction'],
];
}
}