Skip to content

URL 查询参数

Livewire 允许你将组件属性存储在 URL 的查询字符串中。例如,你可能希望组件中的 $search 属性包含在 URL 中:https://example.com/users?search=bob。这对于过滤、排序和分页等功能特别有用,因为它允许用户共享和收藏页面的特定状态。

基本用法

以下是一个 show-users 组件,它允许你通过简单的文本输入按用户名称搜索用户:

php
<?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();
    }
};
blade
<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
<?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",浏览器中的 URL 栏将显示:

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

如果他们现在从新的浏览器窗口加载此 URL,搜索字段将填充"bob",并且用户结果将相应地过滤。

从 URL 初始化属性

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

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

php
use Livewire\Attributes\Url;
use Livewire\Component;

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

    // ...
}

可空属性

默认情况下,如果加载具有空查询字符串条目(如 ?search=)的页面,Livewire 将把该值视为空字符串。在许多情况下,这是预期的,但有时你希望将 ?search= 视为 null

在这些情况下,你可以像这样使用可空类型提示:

php
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 参数来指定查询字符串别名:

php
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]

php
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 参数:

php
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 参数:

php
use Livewire\Attributes\Url;
use Livewire\Component;

class ShowUsers extends Component
{
    #[Url(history: true)]
    public $search = '';

    // ...
}

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

使用 queryString 方法

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

php
use Livewire\Component;

class ShowUsers extends Component
{
    // ...

    protected function queryString()
    {
        return [
            'search' => [
                'as' => 'q',
            ],
        ];
    }
}

Trait 钩子

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

php
trait WithSorting
{
    // ...

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