如何让Livewire组件在页面加载完成后再拉取API数据渲染币种列表
实现方案
你当前的问题核心是将耗时的API请求逻辑写在了render方法中,该方法会在页面首次服务端渲染时就执行,导致阻塞页面加载。可以通过Livewire自带的wire:init特性实现页面加载完成后再异步拉取数据,修改步骤如下:
1. 重构Livewire组件逻辑
将API请求从render方法迁移到init方法中,render仅负责返回视图模板,不执行耗时操作:
namespace App\Http\Livewire\Backend\Crypto; use Livewire\Component; class Cryptolist extends Component { // 存储币种列表数据,初始为空 public array $coins = []; // 存储异常信息 public ?string $errorMsg = null; // 页面加载完成后自动触发的初始化方法 public function init() { try { $api = new \Binance\API('api','secret'); $prices = $api->coins(); $this->coins = json_decode(json_encode($prices, true), true); // 如果使用了第三方DataTable,可在此处触发加载完成事件 $this->dispatch('coinsLoaded'); } catch(\Exception $e) { $this->errorMsg = $e->getMessage(); } } public function render() { if ($this->errorMsg) { return view('wrong')->with('e', $this->errorMsg); } return view('livewire.backend.crypto.cryptolist'); } }
2. 修改组件模板
移除会阻止DOM更新的wire:ignore属性,新增加载状态提示,提升用户体验:
<div wire:init="init"> <!-- 加载中提示 --> <div wire:loading class="py-4 text-center"> <span class="spinner-border spinner-border-sm me-2" role="status" aria-hidden="true"></span> 正在加载币种列表... </div> <!-- 数据加载完成后展示内容 --> <div id="loadesh1" wire:loading.remove> @if(count($coins) > 0) <table class="datatable-init nk-tb-list nk-tb-ulist" data-auto-responsive="false"> <thead> <tr class="nk-tb-item nk-tb-head"> <th class="nk-tb-col"><span class="sub-text">name</span></th> <th class="nk-tb-col tb-col-mb"><span class="sub-text">balance</span></th> </tr> </thead> <tbody> @foreach ($coins as $item => $value) <tr class="nk-tb-item"> <td class="nk-tb-col"> <div class="user-card"> <div class="user-avatar d-none d-sm-flex"> @if(file_exists(public_path() . '/img/crypto/'.strtolower($value['coin'].".svg"))) <img style="border-radius: 0" src="{{ asset('/img/crypto/'.strtolower($value['coin'])) }}.svg" class="img-fluid" alt=""> @else <img style="border-radius: 0" src="https://demo.rayanscript.ir/-/vendor/cryptocurrency-icons/32/color/noimage.png" class="img-fluid" alt=""> @endif </div> <div class="user-info"> <span class="tb-lead english" style="font-weight: bolder">{{$value['name']}}</span> <span class="english">{{$value['coin']}}</span> </div> </div> </td> <td class="nk-tb-col tb-col-mb" data-order="{{$value['coin']}}"> <div class="btn-group" aria-label="Basic example"> <button type="button" class="btn btn-sm btn-dim btn-light" wire:click="getBalance('{{$value['coin']}}')"> <div wire:loading wire:target="getBalance('{{$value['coin']}}')"> <span class="spinner-border spinner-border-sm" role="status" aria-hidden="true"></span> </div> <span class="w-120px" id="coin-{{$value['coin']}}">get balance</span> </button> <button type="button" class="btn btn-sm btn-dim btn-primary">add coin</button> </div> </td> </tr> @endforeach </tbody> </table> @else <div class="py-4 text-center text-muted">暂无币种数据</div> @endif </div> </div>
3. 可选:兼容第三方DataTable初始化
如果你的表格使用了第三方DataTable插件,需要在数据异步加载完成后重新初始化表格,在页面中添加以下JS代码即可:
document.addEventListener('livewire:init', () => { Livewire.on('coinsLoaded', () => { // 替换为你原有DataTable的初始化逻辑即可 NioApp.DataTable('.datatable-init', { autoResponsive: false }); }); });
内容的提问来源于stack exchange,提问作者Awminux
相关产品推荐
相关产品推荐

