主题
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="搜索用户...">
<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] 属性做两件事:
- 写入 URL - 当属性更改时,它更新查询字符串
- 从 URL 读取 - 在页面加载时,它从查询字符串初始化属性
这为您的组件创建了可分享、可收藏的状态。
URL 与 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="搜索产品...">
<select wire:model.live="category">
<option value="all">所有类别</option>
<option value="electronics">电子产品</option>
<option value="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">名称</option>
<option value="price">价格</option>
<option value="created_at">最新</option>
</select>
@foreach($this->products as $product)
<div>{{ $product->name }} - ${{ $product->price }}</div>
@endforeach
</div>用户可以分享如下 URL:
https://example.com/products?q=laptop&category=electronics&minPrice=500&maxPrice=1500&sort=priceSEO 考虑
查询参数会被搜索引擎索引并包含在分析中:
- 对 SEO 有好处 - 每个唯一的查询组合都会创建一个可以被索引的唯一 URL
- 分析跟踪 - 跟踪用户正在使用哪些筛选器和搜索
- 可在社交媒体上分享 - 分享链接时查询参数被保留
了解更多
有关 URL 查询参数的更多信息,包括 queryString() 方法和 trait 钩子,请参阅URL 查询参数文档。