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

Livewire点击日期时Loader不生效问题排查求助

问题排查:点击日期后Timeslot组件Loader未触发显示

核心问题梳理

点击日期选项时,Timeslot组件的Loader未正常显示,直接完成时间段切换。以下是具体问题点及修复方案:


问题点1:事件调度与监听不匹配+同步阻塞

  • Dateslot组件调度的loading事件会和change-dateslot事件一起发送到前端(因为usleep是同步阻塞,Livewire会在方法执行完后批量发送事件),导致Loader刚触发就被关闭。
  • Timeslot组件存在多余的selected-dateslot监听,和实际接收的change-dateslot事件不匹配,易引发逻辑混乱。

问题点2:Loader状态逻辑错误

  • Timeslot内设置$this->isLoading = true后立刻执行数据赋值,马上设为false,整个过程同步完成,前端感知不到状态变化。
  • 前端Alpine代码存在拼写错误:x-data="( isLoading: true }"括号错误、x-show="lisLoading"应为!isLoading,初始Loader状态设置错误。

问题点3:Blade模板语法错误

  • dateslot.blade.php存在标签未闭合、属性拼写错误(wire: click多空格、box-shac应为box-shadow),导致DOM渲染异常,事件绑定失效。
  • timeslot.blade.php存在x-if模板未闭合、循环语法错误,导致时间段渲染异常。

修复后的代码

1. Dateslot.php(修正事件调度逻辑)

class Dateslot extends Component 
{
    public function selectedDateSlot()
    {
        // 优先发送loading事件到Timeslot组件
        $this->dispatch('loading')->to(Timeslot::class);
        
        // 延迟发送日期切换事件,确保Loader有足够时间显示
        $this->dispatch('change-dateslot', [
            'selectedDate' => $this->selectedDate
        ])->to(Timeslot::class)->delay(100);
    }

    public function render()
    {
        return view('livewire.components.dateslot', [
            'days' => $this->days,
            'selectedDate' => $this->selectedDate,
        ]);
    }
}

2. dateslot.blade.php(修正DOM语法错误)

<div class="py-2">
    <div class="flex w-full overflow-x-auto no-scrollbar space-x-3 px-2 scrolling-touch">
        @foreach ($days as $index => $day)
            <div class="shrink-0">
                <input type="radio"
                    wire:model="selectedDate"
                    wire:click="selectedDateSlot"
                    value="{{ $day['datetime'] }}"
                    class="peer hidden no-caret" tabindex="-1" readonly required
                    style="caret-color: transparent; outline: none; box-shadow: none;"/>
                <label class="flex flex-col items-center justify-center w-24 px-4 py-2 text-sm md:text-base text-gray-600 bg-white border border-gray-300 rounded-lg cursor-pointer hover:bg-gray-50 hover:text-black peer-checked:bg-primary-color peer-checked:text-white transition-all duration-300">
                    <span class="text-center">{{ $day['day'] }}</span>
                </label>
            </div>
        @endforeach
    </div>
</div>

3. Timeslot.php(修正Loader状态与事件逻辑)

class Timeslot extends Component
{
    public $isLoading = false;
    public $selectedDate;
    public $slots = [];
    public $doctorslot = []; // 假设该属性已在组件中定义

    #[On('change-dateslot')]
    public function getChangeDateTimeslot($value)
    {
        $this->isLoading = true;
        $this->slots = []; // 立即清空旧时间段
        $this->selectedDate = $value['selectedDate'];
        
        // 异步加载时间段数据(实际项目替换为数据库/API请求)
        $this->dispatch('load-slots')->delay(500);
    }

    #[On('load-slots')]
    public function loadSlots()
    {
        $this->slots = is_array($this->doctorslot[$this->selectedDate] ?? null) 
            ? $this->doctorslot[$this->selectedDate] 
            : [];
        $this->isLoading = false;
        $this->dispatch('stoploading');
    }

    public function render()
    {
        return view('livewire.components.timeslot', [
            'doctorslots' => $this->slots,
            'selectedDate' => $this->selectedDate,
        ]);
    }
}

4. timeslot.blade.php(修正Alpine语法与DOM结构)

<div x-data="{ isLoading: false }"
     x-on:loading.window="isLoading = true"
     x-on:stoploading.window="isLoading = false"
>
    <!-- Loader 显示区域 -->
    <template x-if="isLoading">
        <div class="text-center py-2 text-gray-500">Loading...</div>
    </template>

    <!-- 时间段显示区域 -->
    <div x-show="!isLoading" class="mt-2">
        @if(count($doctorslots))
            <div class="grid grid-cols-3 sm:grid-cols-4 md:grid-cols-5 lg:grid-cols-8 gap-2">
                @foreach ($doctorslots as $slotKey => $slot)
                    <div wire:key="slot-{{ $slotKey }}">
                        <input type="radio"
                            wire:model="selectedSlot" 
                            wire:click="selectedTime"
                            id="timeslot-{{ $slotKey }}"
                            name="selectedSlot" 
                            class="hidden peer" 
                            value="{{ $slot }}">
                        <label for="timeslot-{{ $slotKey }}" class="block text-center py-2 border rounded cursor-pointer peer-checked:bg-primary-color peer-checked:text-white">
                            {{ $slot }}
                        </label>
                    </div>
                @endforeach
            </div>
        @else
            <div class="text-center py-2 text-gray-500">No slots available for this date</div>
        @endif
    </div>
</div>

额外注意事项

  • 确保Livewire与Alpine.js版本兼容,避免事件监听失效。
  • 实际项目中,将模拟的延迟逻辑替换为真实的异步数据获取(如数据库查询、第三方API请求)。
  • 组件视图路径需与项目结构对应(如livewire.components.dateslot对应resources/views/livewire/components/dateslot.blade.php)。

内容的提问来源于stack exchange,提问作者Muhammed Fayaz

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.12 20:35:56