惰性加载

您是视觉学习者吗?
通过我们深入的屏幕录像掌握 Livewire
立即观看

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 模型将被传递到 Revenuemount() 方法中。但是,由于我们不会在下一个网络请求之前运行 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(),而是渲染完整组件,就好像根本没有应用惰性加载一样。