AlpineJS加载更多动画异常:初始index设10无效,设9正常
AlpineJS加载更多动画不触发的原因及修复方案
问题背景
当AlpineJS的index初始值设为10、每次增量为10时,加载更多动画无法触发;但将index设为9、增量设为9时,动画正常运行。后端共有20条数据,期望页面初始显示10条,点击按钮加载剩余10条并触发动画。
核心原因
新加载的元素在Livewire更新DOM后,x-show的条件已经直接满足,没有经历「隐藏→显示」的状态转变,所以Alpine的enter动画不会触发:
- 初始
index=10时,前10条数据的$loop->index是0-9,index > $loop->index全部为true,x-init设置show=true后,这10条直接显示。 - 点击加载更多时,先把
index改成20再调用$wire.loadMore(),Livewire更新DOM后,新增数据的$loop->index是10-19,此时show已经是true,index=20 > 10-19也全部为true,新元素刚渲染就满足显示条件,无状态变化,动画不触发。 - 而
index=9、增量9时,初始有1条数据($loop->index=9)不满足显示条件,点击后该数据及新加载的部分数据从隐藏变为显示,触发动画。
修复方案
方案1:监听Livewire加载完成事件,延迟更新index
先让Livewire完成DOM更新,再调整index,确保新元素初始处于隐藏状态,之后再切换为显示。
前端代码修改
<div x-data="{ show: false, index: 10 }" x-on:load-more-complete.window="index += {{ $totalTributes - count($tributes) < 10 ? $totalTributes - count($tributes) : 10 }}"> <div class="grid grid-cols-2 md:grid-cols-2 lg:grid-cols-5 gap-4 md:gap-6 lg:gap-6 mt-4"> @foreach($tributes as $tribute) <div class="gallery-border p-8" x-show="show && index > {{$loop->index}}" x-transition:enter="transition ease-out duration-500" x-transition:enter-start="opacity-0" x-transition:enter-end="opacity-100"> <p class="text-2xl md:text-4xl lg:text-4xl">{{ $tribute->message }}</p> <p class="text-sm">-{{ $tribute->name }}</p> </div> @endforeach </div> @if(count($tributes) < $totalTributes) <div class="text-center mt-4"> <button x-on:click="show = true; $wire.loadMore()" x-init="setTimeout(() => { show = true }, 500)" class="tributes-gallery-load-more">Load More</button> </div> @endif
后端Livewire代码修改
在loadMore方法末尾添加事件分发:
public function loadMore() { $this->page++; $newTributes = Tribute::where('status', 'approved') ->orderBy('id', 'desc') ->skip(($this->page - 1) * $this->perPage) ->take($this->perPage) ->get(); $this->tributes = $this->tributes->concat($newTributes); // 分发加载完成事件,通知前端更新index $this->dispatch('load-more-complete'); }
方案2:改用「已加载数量」控制显示逻辑
用loadedCount替代index,初始值为10,加载后增加对应数量,通过$loop->index < loadedCount控制显示,让新元素从隐藏状态切换为显示,触发动画。
前端代码修改
<div x-data="{ show: false, loadedCount: 10 }"> <div class="grid grid-cols-2 md:grid-cols-2 lg:grid-cols-5 gap-4 md:gap-6 lg:gap-6 mt-4"> @foreach($tributes as $tribute) <div class="gallery-border p-8" x-show="show && {{$loop->index}} < loadedCount" x-transition:enter="transition ease-out duration-500" x-transition:enter-start="opacity-0" x-transition:enter-end="opacity-100"> <p class="text-2xl md:text-4xl lg:text-4xl">{{ $tribute->message }}</p> <p class="text-sm">-{{ $tribute->name }}</p> </div> @endforeach </div> @if(count($tributes) < $totalTributes) <div class="text-center mt-4"> @php $remaining = $totalTributes - count($tributes); @endphp @if($remaining < 10) <button x-on:click="show = true; loadedCount += {{$remaining}}; $wire.loadMore()" x-init="setTimeout(() => { show = true }, 500)" class="tributes-gallery-load-more">Load More</button> @else <button x-on:click="show = true; loadedCount += 10; $wire.loadMore()" x-init="setTimeout(() => { show = true }, 500)" class="tributes-gallery-load-more">Load More</button> @endif </div> @endif
后端代码无需修改,保持原有逻辑即可。
内容的提问来源于stack exchange,提问作者Markwow
相关产品推荐
相关产品推荐

