Після кожної дії сервер повертає новий HTML компонента. Livewire не замінює ним старий цілком, а морфить: проходить обидва дерева елемент за елементом і змінює лише те, що відрізняється. Завдяки цьому зберігаються фокус, введений текст, позиція прокрутки й обробники подій.
Де морфінг помиляється. Алгоритм порівнює елементи за позицією. Якщо між ними з'являється новий елемент, він може «зсунути» відповідність:
<div><input wire:model="title"></div>
@if ($errors->has('title'))
<div>{{ $errors->first('title') }}</div>
@endif
<div><button>Зберегти</button></div>
Коли з'являється помилка, Livewire бачить на другому місці новий div і може вирішити, що це змінений старий, - результат: зайві перерисовки, втрачений стан сторонніх елементів. Livewire додає в шаблон службові маркери навколо @if і @foreach, щоб це згладити, але найнадійніший інструмент - ключі.
wire:key - ідентичність елемента:
@foreach ($todos as $todo)
<li wire:key="todo-{{ $todo->id }}">...</li>
@endforeach
Morph зіставляє елементи за ключем, а не за позицією: видалення першого рядка не змушує «перейменовувати» всі наступні. Для дочірніх компонентів у циклі ключ обов'язковий.
wire:ignore - не чіпати вміст елемента взагалі:
<div wire:ignore>
<div x-init="new Chart($el, ...)"></div>
</div>
Для сторонніх бібліотек (редактори, графіки, карти), які самі керують своїм DOM: інакше Livewire «виправить» їхні зміни назад до HTML з сервера. wire:ignore.self - ігнорувати атрибути самого елемента, але оновлювати дітей.
wire:replace - протилежне: не морфити, а замінити вміст повністю:
<div wire:replace>
<json-viewer>@json($payload)</json-viewer>
</div>
Для веб-компонентів і елементів зі своїм внутрішнім станом, який треба скинути при кожному оновленні. wire:replace.self - замінити й сам елемент.
Типові симптоми й причини:
| Симптом |
Причина |
| введене «переїжджає» в інше поле |
немає wire:key у циклі |
| сторонній віджет зникає чи ламається після дії |
немає wire:ignore |
| елемент зберігає старий стан, хоча дані змінилися |
морф перевикористав елемент - wire:key зі зміною ключа чи wire:replace |
| дочірній компонент не перестворюється |
той самий wire:key - змінити ключ, щоб Livewire створив новий екземпляр |
Продуктивність: морфінг великого HTML (таблиця на тисячі рядків) коштує і на сервері (рендер), і в браузері (порівняння). Острівці, ліниві компоненти й пагінація зменшують обсяг, який морфиться за одну дію.
Докладніше в документації: Livewire: морфінг