You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Livewire 2.6:基于updateWaitTime事件切换模板及按钮点击失效排查

解决Livewire中Resend按钮wire:click不生效及倒计时模板切换问题

问题核心原因

  1. 动态DOM事件绑定失效:Alpine.js的<template>动态渲染元素,Livewire无法自动为其注册wire:click事件监听。
  2. Alpine实例状态未同步:收到updateWaitTime事件时,直接调用otpSend()仅创建新对象,未更新页面已存在的Alpine组件实例状态。
  3. 倒计时逻辑漏洞:getTime()返回毫秒值,倒计时结束后未重置状态,导致按钮无法正确显示。

修复方案

1. 重构Alpine组件,支持外部状态更新

修改otpSend函数,新增updateWaitTime方法用于接收Livewire传递的倒计时时长,同步更新组件内部状态:

function otpSend(initialWaitTime = 0) {
    const milliseconds = initialWaitTime * 1000;
    const currentDate = Date.now() + milliseconds;
    return {
        countDown: milliseconds,
        countDownTimer: currentDate,
        intervalID: null,
        init() {
            this.startTimer();
        },
        startTimer() {
            if (this.intervalID) clearInterval(this.intervalID);
            this.intervalID = setInterval(() => {
                this.countDown = this.countDownTimer - Date.now();
                if (this.countDown <= 0) this.clearTimer();
            }, 1000);
        },
        updateWaitTime(waitTime) {
            const newMilliseconds = waitTime * 1000;
            this.countDownTimer = Date.now() + newMilliseconds;
            this.countDown = newMilliseconds;
            this.startTimer();
        },
        getTime() {
            return Math.max(this.countDown, 0); // 确保返回值不小于0
        },
        formatTime() {
            return new Date(this.getTime()).toLocaleTimeString(navigator.language, {
                minute: '2-digit',
                second: '2-digit'
            });
        },
        clearTimer() {
            clearInterval(this.intervalID);
            this.intervalID = null;
        }
    }
}

2. 调整HTML结构,确保Livewire事件绑定有效

添加wire:key标识动态元素,用x-ref绑定Alpine实例,方便后续调用:

<div class="d-flex justify-content-end"
     x-data="otpSend(@entangle('wait_before_resend'))"
     x-ref="otpTimer"
     x-init="init()"
>
    <template x-if="getTime() <= 0">
        <button wire:click="getOTPCode(true)" wire:key="resend-button" type="button"
                class="my-2 btn btn-primary rounded-pill text-white">
            <i class="bi bi-arrow-counterclockwise"></i> Resend Code
        </button>
    </template>
    <template x-if="getTime() > 0">
        <small wire:key="countdown-text">
            Resend OTP in
            <span x-text="formatTime()"></span>
        </small>
    </template>
    <button hidden id="hide" data-bs-dismiss="modal"></button>
</div>

3. 修改Livewire事件监听,更新Alpine实例状态

通过Alpine.raw()获取组件实例,直接调用内部方法更新状态,而非重新创建实例:

document.addEventListener('livewire:load', function () {
    const otpTimerEl = document.querySelector('[x-ref="otpTimer"]');
    
    window.livewire.on('submitted', function () {
        resetForm();
        focusForm();
    })

    window.livewire.on('resent', function () {
        resetForm();
        focusForm();
    })

    window.livewire.on('updateWaitTime', function (wait_before_resend) {
        console.log(`updateWaitTime ${wait_before_resend}`);
        Alpine.raw(otpTimerEl).updateWaitTime(wait_before_resend);
    })

    window.livewire.on('success', function () {
        setTimeout(() => {
            $('#hide').click();
            @this.emitSelf('reset');
        }, 500)
    })
})

4. 优化Livewire后端逻辑

确保组件属性初始化正确,getOTPCode方法逻辑完整:

public $wait_before_resend = 60; // 默认60秒倒计时

public function getOTPCode($resend = false)
{
    // 此处添加发送OTP的业务逻辑
    
    // 触发事件更新倒计时
    $this->emit('updateWaitTime', $this->wait_before_resend);
}

关键说明

  • wire:key:为动态元素添加唯一标识,确保Livewire正确追踪DOM变化,避免事件绑定丢失。
  • Alpine.raw():直接获取Alpine组件实例,实现前后端状态同步更新。
  • @entangle:将Livewire属性与Alpine初始值绑定,实现组件初始化时的状态同步。

内容的提问来源于stack exchange,提问作者Eli Volowelsky

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.16 14:37:33