Skip to content

#[Url]

#[Url] 属性将属性的值存储在 URL 的查询字符串中,允许用户共享和收藏页面的特定状态。

基本用法

#[Url] 属性应用于任何应在 URL 中持久化的属性:

php
<?php // resources/views/components/user/⚡index.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();
    }
};
?>

<div>
    <input type="text" wire:model.live="search" placeholder="Search users...">

    <ul>
        @foreach ($this->users as $user)
            <li wire:key="{{ $user->id }}">{{ $user->name }}</li>
        @endforeach
    </ul>
</div>

当用户在搜索字段中输入 "bob" 时,URL 更新为 https://example.com/users?search=bob。如果他们分享此 URL 或刷新页面,搜索值将保持不变。

工作原理

#[Url] 属性做两件事:

  1. 写入 URL - 当属性更改时,它更新查询字符串
  2. 从 URL 读取 - 在页面加载时,它从查询字符串初始化属性

这为你的组件创建了可共享、可收藏的状态。

URL vs Session

#[Url]#[Session] 都可以持久化属性值,但有不同的权衡:

特性#[Url]#[Session]
跨刷新持久化
分享 URL 时持久化
保持 URL 简洁
对用户可见
可共享状态

当你希望用户能够共享或收藏当前状态时使用 #[Url]。当状态应该是私有的时使用 #[Session]

使用别名

使用 as 参数缩短或混淆 URL 中的属性名称:

php
<?php // resources/views/components/user/⚡index.blade.php

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

new class extends Component {
    #[Url(as: 'q')] // [tl! highlight]
    public $search = '';
};

URL 将显示 ?q=bob 而不是 ?search=bob

排除值

默认情况下,Livewire 仅在值与初始值不同时添加查询参数。使用 except 自定义此行为:

php
<?php // resources/views/components/user/⚡index.blade.php

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

new class extends Component {
    #[Url(except: '')] // [tl! highlight]
    public $search = '';

    public function mount()
    {
        $this->search = auth()->user()->username;
    }
};

现在 Livewire 只会在 search 为空字符串时从 URL 中排除它,而不是在它等于初始用户名值时。

始终在 URL 中显示

要始终在 URL 中包含参数,即使为空,使用 keep

php
#[Url(keep: true)] // [tl! highlight]
public $search = '';

即使值为空,URL 也将始终显示 ?search=

可空属性

使用可空类型提示将空查询参数视为 null 而不是空字符串:

php
<?php // resources/views/components/user/⚡index.blade.php

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

new class extends Component {
    #[Url]
    public ?string $search; // [tl! highlight]
};

现在 ?search=$search 设置为 null 而不是 ''

浏览器历史

默认情况下,Livewire 使用 history.replaceState() 修改 URL 而不添加浏览器历史记录。要添加历史记录(使后退按钮恢复之前的查询值),使用 history

php
#[Url(history: true)] // [tl! highlight]
public $search = '';

现在点击浏览器的后退按钮将恢复之前的搜索值,而不是导航到上一页。

何时使用

在以下情况使用 #[Url]

  • 构建搜索或过滤界面
  • 实现分页
  • 创建可共享的视图(地图位置、选定的过滤器等)
  • 允许用户收藏特定状态
  • 支持通过浏览器后退/前进按钮在状态之间导航

示例:产品过滤

这是一个使用多个 URL 参数过滤产品的实际示例:

php
<?php // resources/views/pages/⚡products.blade.php

use Livewire\Attributes\Computed;
use Livewire\Attributes\Url;
use Livewire\Component;
use App\Models\Product;

new class extends Component {
    #[Url(as: 'q')]
    public $search = '';

    #[Url]
    public $category = 'all';

    #[Url]
    public $minPrice = 0;

    #[Url]
    public $maxPrice = 1000;

    #[Url]
    public $sort = 'name';

    #[Computed]
    public function products()
    {
        return Product::query()
            ->when($this->search, fn($q) => $q->search($this->search))
            ->when($this->category !== 'all', fn($q) => $q->where('category', $this->category))
            ->whereBetween('price', [$this->minPrice, $this->maxPrice])
            ->orderBy($this->sort)
            ->paginate(20);
    }
};
?>

<div>
    <input type="text" wire:model.live="search" placeholder="Search products...">

    <select wire:model.live="category">
        <option value="all">All Categories</option>
        <option value="electronics">Electronics</option>
        <option value="clothing">Clothing</option>
    </select>

    <input type="range" wire:model.live="minPrice" min="0" max="1000">
    <input type="range" wire:model.live="maxPrice" min="0" max="1000">

    <select wire:model.live="sort">
        <option value="name">Name</option>
        <option value="price">Price</option>
        <option value="created_at">Newest</option>
    </select>

    @foreach($this->products as $product)
        <div wire:key="{{ $product->id }}">{{ $product->name }} - ${{ $product->price }}</div>
    @endforeach
</div>

用户可以分享如下 URL:

https://example.com/products?q=laptop&category=electronics&minPrice=500&maxPrice=1500&sort=price

SEO 注意事项

查询参数被搜索引擎索引并包含在分析中:

  • 对 SEO 有利 - 每个唯一的查询组合创建一个可以被索引的唯一 URL
  • 分析跟踪 - 跟踪用户使用哪些过滤器和搜索
  • 社交媒体可分享 - 分享链接时查询参数会被保留

了解更多

有关 URL 查询参数的更多信息,包括 queryString() 方法和 trait 钩子,请参阅 URL 查询参数文档

参考

php
#[Url(
    ?string $as = null,
    bool $history = false,
    bool $keep = false,
    mixed $except = null,
    mixed $nullable = null,
)]
参数类型默认值描述
$as?stringnullURL 中查询参数的自定义名称
$historyboolfalse将 URL 更改推送到浏览器历史(启用后退按钮)
$keepboolfalse导航离开时保留查询参数
$exceptmixednull从 URL 中排除的值
$nullablemixednullURL 中缺少查询参数时使用的值