Livewire异步调用Stripe接口时如何让loading状态持续到请求完成
问题根源
你的loading状态提前消失有两个核心原因:
- Livewire 原生的
wire:loading只能监听后端方法的调用周期,你前端调用 StripeconfirmCardSetup是独立的 JS 异步请求,这段请求过程不会触发 Livewire 的 loading 状态 - 原代码调用
@this.addPaymentMethod时没有加await,JS 不会等待 Livewire 后端请求执行完成,导致 loading 刚触发就提前结束,甚至重定向还没完成就消失了
修复方案
我们直接手动控制 loading 显隐,覆盖从提交表单到重定向的全流程:
第一步:修改表单HTML,移除自带的wire:loading绑定
<form id="card-form"> <label>Card details</label> <div id="card-element"></div> <button class="button round" id="card-button">Add payment card</button> <!-- Loading spinner 默认隐藏 --> <svg id="loading-spinner" class="hidden inline-block animate-spin h-5 w-5 text-white" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24"> <circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"></circle> <path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path> </svg> </form>
第二步:修改JS代码,手动控制状态、等待异步请求完成
注意同时修正原代码里的笔误:confirmCardSetup 里的card参数应该是你创建的cardElement,不是不存在的cardNumber
const stripe = Stripe('stripe-public-key'); const elements = stripe.elements(); const form = document.getElementById('card-form') const cardButton = document.getElementById('card-button'); const loadingSpinner = document.getElementById('loading-spinner'); const cardElement = elements.create('card'); cardElement.mount('#card-element'); form.addEventListener('submit', async (e) => { e.preventDefault(); // 提交后立刻切换为loading状态 cardButton.disabled = true; cardButton.classList.add('hidden'); loadingSpinner.classList.remove('hidden'); try { const { setupIntent, error } = await stripe.confirmCardSetup( clientSecret, { payment_method: { card: cardElement, // 修正原笔误 billing_details: { name: 'Oliver' } } } ); if (error) { // 出错恢复原始状态 console.log(error.message) resetLoadingState() return } // 等待Livewire后端方法执行完成,重定向会自动触发 await @this.addPaymentMethod(setupIntent.payment_method) } catch (e) { console.error(e) resetLoadingState() } }); // 封装状态重置方法 function resetLoadingState() { cardButton.disabled = false; cardButton.classList.remove('hidden'); loadingSpinner.classList.add('hidden'); }
后端PHP代码不需要做任何修改。
内容的提问来源于stack exchange,提问作者oliverbj
相关产品推荐
相关产品推荐

