Livewire DOM Diffing问题:输入框失焦如何解决?
Livewire 标签输入框添加后失焦问题解决
问题场景
现有Livewire Blade模板代码如下:
<div class="box-wrapper"> <ul> @foreach($tags as $tag) <li wire:key="tag-{{ $loop->index }}"> {{ $tag }} </li> @endforeach <input type="text" wire:model.defer="tagInputValue" wire:key="tag-input" wire:keydown.enter="add()" /> </ul> </div>
按下Enter执行add()方法时,会将输入值追加到$tags数组并重置输入框值,但每次操作后输入框会失焦,影响体验。已尝试将<input>移到<ul>外或循环前,但均不符合布局/样式要求。
问题原因
核心问题出在<li>的wire:key使用了$loop->index:
- 每次新增标签后,原有标签对应的
$loop->index会递增,导致它们的wire:key值发生变化 - Livewire的DOM diffing机制会将这些
<li>判定为全新元素,重新渲染整个foreach生成的列表 - 尽管
<input>有独立的wire:key,但它紧跟在循环之后,当前面的列表被完全重新渲染时,Livewire会重新生成<ul>的所有子元素,包括该输入框,最终导致输入框失焦
解决方案
将<li>的wire:key改为基于标签内容的唯一标识(因add()方法会检查重复,标签内容本身唯一):
<div class="box-wrapper"> <ul> @foreach($tags as $tag) <!-- 改用标签内容作为wire:key的唯一标识 --> <li wire:key="tag-{{ $tag }}"> {{ $tag }} </li> @endforeach <input type="text" wire:model.defer="tagInputValue" wire:key="tag-input" wire:keydown.enter="add()" /> </ul> </div>
修改后:
- 新增标签时,原有
<li>的wire:key不会改变,Livewire只会在列表末尾新增一个<li>元素,不会重新渲染原有内容 <input>不会被重新创建,仅会被重置输入值,因此能保持焦点
如果存在标签内容重复的场景(即使add()做了校验,也可提前为每个标签分配唯一ID),可改用ID作为wire:key,比如:
<li wire:key="tag-{{ $tag->id }}"> {{ $tag->name }} </li>
内容的提问来源于stack exchange,提问作者Rusurano
相关产品推荐
相关产品推荐

