URL 查询参数
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
值为空字符串时从查询字符串中排除 search
,except
参数已添加到 #[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'], ]; }}