惰性加载
Livewire 允许您惰性加载组件,否则这些组件会减慢初始页面加载速度。
例如,假设您有一个 Revenue
组件,其中包含 mount()
中的缓慢数据库查询
<?php namespace App\Livewire; use Livewire\Component;use App\Models\Transaction; class Revenue extends Component{ public $amount; public function mount() { // Slow database query... $this->amount = Transaction::monthToDate()->sum('amount'); } public function render() { return view('livewire.revenue'); }}
<div> Revenue this month: {{ $amount }}</div>
如果没有惰性加载,此组件将延迟整个页面的加载并使您的整个应用程序感觉缓慢。
要启用惰性加载,您可以将 lazy
参数传递到组件中
<livewire:revenue lazy />
现在,Livewire 不会立即加载组件,而是跳过此组件,在没有它时加载页面。然后,当组件在视口中可见时,Livewire 将发出网络请求以在页面上完全加载此组件。
与 Livewire 中的其他网络请求不同,惰性加载更新在发送到服务器时彼此隔离。这通过在页面加载时并行加载每个组件来保持惰性加载的快速性。 在此处阅读有关禁用此行为的更多信息 →
呈现占位符 HTML
默认情况下,Livewire 会在组件完全加载之前为其插入一个空的 <div></div>
。由于组件最初对用户不可见,因此当组件突然出现在页面上时可能会令人不安。
要向用户发出组件正在加载的信号,您可以定义一个 placeholder()
方法来呈现您喜欢的任何类型的占位符 HTML,包括加载旋转器和骨架占位符
<?php namespace App\Livewire; use Livewire\Component;use App\Models\Transaction; class Revenue extends Component{ public $amount; public function mount() { // Slow database query... $this->amount = Transaction::monthToDate()->sum('amount'); } public function placeholder() { return <<<'HTML' <div> <!-- Loading spinner... --> <svg>...</svg> </div> HTML; } public function render() { return view('livewire.revenue'); }}
由于上述组件通过从 placeholder()
方法返回 HTML 来指定“占位符”,因此在组件完全加载之前,用户将在页面上看到 SVG 加载旋转器。
例如,如果占位符的根元素类型是“div”,则组件也必须使用“div”元素。
通过视图呈现占位符
对于更复杂的加载器(例如骨架),您可以从 placeholder()
返回一个 view
,类似于 render()
。
public function placeholder(array $params = []){ return view('livewire.placeholders.skeleton', $params);}
作为延迟加载的组件的任何参数都将作为传递给 placeholder()
方法的 $params
参数提供。
在视口外延迟加载
默认情况下,延迟加载的组件在进入浏览器的视口之前不会完全加载,例如当用户滚动到其中一个组件时。
如果您希望在页面加载后立即延迟加载页面上的所有组件,而无需等待它们进入视口,您可以通过将“on-load”传递到 lazy
参数中来实现。
<livewire:revenue lazy="on-load" />
现在,此组件将在页面准备就绪后加载,而无需等待它进入视口。
传递道具
通常,您可以将 lazy
组件视为与普通组件相同,因为您仍然可以从外部向其中传递数据。
例如,以下是一个场景,您可能从父组件将时间间隔传递到 Revenue
组件
<input type="date" wire:model="start"><input type="date" wire:model="end"> <livewire:revenue lazy :$start :$end />
您可以像其他任何组件一样在 mount()
中接受此数据
<?php namespace App\Livewire; use Livewire\Component;use App\Models\Transaction; class Revenue extends Component{ public $amount; public function mount($start, $end) { // Expensive database query... $this->amount = Transactions::between($start, $end)->sum('amount'); } public function placeholder() { return <<<'HTML' <div> <!-- Loading spinner... --> <svg>...</svg> </div> HTML; } public function render() { return view('livewire.revenue'); }}
但是,与普通组件加载不同,lazy
组件必须序列化或“脱水”任何传入的属性,并将其暂时存储在客户端,直到组件完全加载。
例如,您可能希望像这样将 Eloquent 模型传递到 Revenue
组件
<livewire:revenue lazy :$user />
在普通组件中,实际的 PHP 内存中的 $user
模型将被传递到 Revenue
的 mount()
方法中。但是,由于我们不会在下一个网络请求之前运行 mount()
,因此 Livewire 会在内部将 $user
序列化为 JSON,然后在下一次请求处理之前从数据库中重新查询它。
通常,此序列化不应导致应用程序中的任何行为差异。
默认延迟加载
如果你希望强制所有组件的使用都延迟加载,可以在组件类上方添加 #[Lazy]
属性
<?php namespace App\Livewire; use Livewire\Component;use Livewire\Attributes\Lazy; #[Lazy]class Revenue extends Component{ // ...}
如果你希望覆盖延迟加载,可以将 lazy
参数设置为 false
<livewire:revenue :lazy="false" />
禁用请求隔离
如果页面上有多个延迟加载的组件,每个组件都会进行独立的网络请求,而不是将每个延迟更新捆绑到一个请求中。
如果你希望禁用此隔离行为,而是将所有更新捆绑到一个网络请求中,可以使用 isolate: false
参数来实现
<?php namespace App\Livewire; use Livewire\Component;use Livewire\Attributes\Lazy; #[Lazy(isolate: false)] class Revenue extends Component{ // ...}
现在,如果同一页面上有十个 Revenue
组件,当页面加载时,所有十个更新都将被捆绑并作为单个网络请求发送到服务器。
全页延迟加载
你可能希望延迟加载全页 Livewire 组件。你可以像这样在路由上调用 ->lazy()
来实现
Route::get('/dashboard', \App\Livewire\Dashboard::class)->lazy();
或者,如果有一个默认延迟加载的组件,而你希望选择不进行延迟加载,可以使用以下 enabled: false
参数
Route::get('/dashboard', \App\Livewire\Dashboard::class)->lazy(enabled: false);
默认占位符视图
如果你希望为所有组件设置默认占位符视图,可以在 /config/livewire.php
配置文件中引用视图来实现
'lazy_placeholder' => 'livewire.placeholder',
现在,当延迟加载组件并且没有定义 placeholder()
时,Livewire 将使用已配置的 Blade 视图(在本例中为 livewire.placeholder
)。
禁用测试的延迟加载
在对惰性组件或包含嵌套惰性组件的页面进行单元测试时,你可能希望禁用“惰性”行为,以便你可以断言最终渲染的行为。否则,这些组件将在测试期间作为其占位符进行渲染。
你可以使用 Livewire::withoutLazyLoading()
测试助手轻松禁用惰性加载,如下所示
<?php namespace Tests\Feature\Livewire; use App\Livewire\Dashboard;use Livewire\Livewire;use Tests\TestCase; class DashboardTest extends TestCase{ /** @test */ public function renders_successfully() { Livewire::withoutLazyLoading() ->test(Dashboard::class) ->assertSee(...); }}
现在,当为此测试渲染仪表盘组件时,它将跳过渲染 placeholder()
,而是渲染完整组件,就好像根本没有应用惰性加载一样。