我想快速解释一下情况。本质上,我创建了一个 Livewire 组件,它允许我从无线电 API 获取数据来获取歌曲。这些歌曲每 3 分钟更改一次,只要此 API 的属性发生更改,我就想更新我的 Blade 视图。
class TitleSong extends Component
{
public $songTitle;
public $songArtist;
public $songImage;
public $secondsTotal;
public $secondsElapsed;
public $elementToShow;
public $remainingTime;
public function render()
{
return view('livewire.title-song');
}
public function boot()
{
$this->fetchSongData();
}
public function fetchSongData()
{
try{
$response = Http::get('MY API');
$data = $response->json();
$this->songArtist = $data['song']['artist'];
$this->secondsElapsed = $data['song']['seconds_elapsed'];
$this->secondsTotal = $data['song']['seconds_total'];
$this->songImage = $data['song']['art'];
$this->songTitle = $data['song']['title'];
$remainingTime = $this->secondsTotal - $this->secondsElapsed;
$this->remainingTime = $remainingTime;
} catch (\Throwable $th) {
dd($th->getMessage());
}
}
}
由于这些元素需要在整个文档中拆分,因此我使用新变量“$elementToShow”使其成为可能,这就是视图:
<div wire:poll.{{$remainingTime}}="fetchSongData">
@if ($elementToShow === 'songTitle')
<h1 id="songTitle" style="color: var(--quaternary-color); font-weight: 600" class="text-4xl">{{$songTitle}}</h1>
@elseif ($elementToShow === 'songArtist')
<p id="songArtist" class="mt-2 ml-1" style="color: var(--quinary-color); font-weight: 400; font-size: 15px">{{$songArtist}}</p>
@elseif ($elementToShow === 'secondsElapsed')
<span id="secondsElapsed" class="current-time">0:00</span>
@elseif ($elementToShow === 'secondsTotal')
<span id="secondsTotal" class="total-time"> {{substr($secondsTotal, 0, 1) . ':' . substr($secondsTotal, 1, 2)}}</span>
@elseif($elementToShow === 'songImage')
<img style="position: absolute; left: 12%; top: 2%; border-radius:20px; z-index: 1" width="220px" height="200px" src="{{$songImage}}" />
@endif
</div>
现在我想问你是否有更好的方法来做到这一点而不使用wire:poll或其他东西。不幸的是,这给我带来了很多痛苦,因为它极大地影响了我网站的速度。该网站现在需要 5 秒才能加载 HTML 文档。
我不知道为什么这个 API 调用要花很长时间来加载,也许是 Livewire 组件的原因,但我尝试在这里和那里做一些优化,并使用 Laravel Debug。
好吧,所提供的代码中有一些不好的做法,所以我将解决这个问题以及您正在寻求帮助的原始问题。
您只需将 Lazy 属性添加到带电线路附带的类中,或者添加到父视图或路由中。以下是如何向组件添加 Lazy 属性。
use Livewire\Component;
use Livewire\Attributes\Lazy; // Import The Attribute
#[Lazy]
class SongTitle extends Component
{
public function mount() {
// Resolve Song From API HERE
}
您也不应该使用 Boot 方法。每次用户和服务器通信时(而不是首次渲染组件时)都会触发此方法。您最终可能会无缘无故地反复向 API 请求歌曲,这将锁定您的应用程序并极大地减慢您的应用程序速度。
官方文档中有更多详细信息 - Livewire Lazy Loading
为了解决这个问题,我们可以延迟加载歌曲的数据。
客户端和服务器之间的每个请求都会触发引导方法。您可以向此 API 端点发送许多请求来获取歌曲数据,并在不需要获取歌曲数据时阻止请求,因为所需的数据没有发生任何变化。
我们应该将此功能移至 Mount。这只会发送一次歌曲数据的 API 请求,但如果将来需要,您仍然可以手动发送另一个请求。
您可以在 Livewire 文档中阅读更多相关信息 - Lifecycle Hooks
当您浏览非“单页应用程序”的标准网站时,您的 Web 浏览器(例如 Google Chrome)会向 Web 服务器发送页面请求。 有时,我们会遇到服务器需要一段时间才能响应的情况,因为它正在处理构建此 HTML 文件所需的所有内容。
为了解决这个问题,我们可以使用延迟加载,Livewire 本身就支持延迟加载。这在整个互联网上被广泛使用来解决您当前遇到的问题。简而言之,服务器将使用 HTML 文件进行响应,Javascript 将在客户端的 Web 浏览器中运行,它将处理获取这些额外数据并更新页面。
Livewire 特定上下文
如何在 Livewire 中延迟加载
尽管有几种方法可以实现此功能,但实现此功能很简单。我无法想象默认情况下我们不希望这种延迟加载,所以我建议的方法是将属性添加到组件类中,如下所示:
use Livewire\Component;
use Livewire\Attributes\Lazy; // Import The Attribute
#[Lazy]
class SongTitle extends Component
{
其他改进
这是类的改进示例,您可以在几分钟内将其实现到代码库中:
#[Lazy]
class TitleSong extends Component
{
// set types on your variables
public string $songTitle;
public string $songArtist;
public string $songImage;
public int $secondsTotal;
public int $secondsElapsed;
public $elementToShow;
public int $remainingTime;
public function mount(): void
{
$this->resolveSong();
}
public function resolveSong(): void
{
// Logic for API stuff here
}
我建议研究的进一步改进包括创建一个服务来处理 API 通信以获取歌曲数据。
我创建了一个 GIST,其中包含一些适合您提供的上下文的示例类。它没有涉及很多细节,但我希望它可以直观地理解,所以这不是太大的问题。
歌曲标题清理 - Gist