Smart Keys
Директива wire:key позволяет Livewire эффективно отслеживать
изменения в списках, рендерящихся через директиву @foreach.
В отличие от статических ключей в Laravel, умные ключи автоматически
генерируются на основе содержимого или индекса элемента.
Это позволяет Livewire минимизировать количество обновлений DOM
при изменении данных коллекции.
При работе со списками Livewire автоматически генерирует ключи для отслеживания элементов. Однако в сложных компонентах может потребоваться явное указание ключа для корректной работы с состоянием элементов.
Синтаксис
Директива wire:key используется внутри цикла @foreach
и в качестве значения принимает уникальный идентификатор элемента:
@foreach ($items as $item)
<div wire:key="{{ $item->id }}">
{{ $item->name }}
</div>
@endforeach
Пример
Рассмотрим компонент, который отображает список задач и позволяет удалять их по клику:
<?php
namespace AppLivewire;
use LivewireComponent;
class TaskList extends Component
{
public $tasks = [
['id' => 1, 'name' => 'Task 1'],
['id' => 2, 'name' => 'Task 2'],
['id' => 3, 'name' => 'Task 3'],
];
public function deleteTask($id)
{
$this->tasks = array_filter(
$this->tasks,
fn($task) => $task['id'] !== $id
);
}
public function render()
{
return view('livewire.task-list');
}
}
?>
<div>
@foreach ($tasks as $task)
<div wire:key="{{ $task['id'] }}">
{{ $task['name'] }}
<button wire:click="deleteTask({{ $task['id'] }})">
Delete
</button>
</div>
@endforeach
</div>
Результат выполнения кода до удаления:
<div>
<div>
Task 1
<button>Delete</button>
</div>
<div>
Task 2
<button>Delete</button>
</div>
<div>
Task 3
<button>Delete</button>
</div>
</div>
При нажатии на кнопку "Delete" соответствующая задача удаляется, и Livewire с помощью умных ключей корректно обновляет список, не пересоздавая остальные элементы.
Пример
Умные ключи также работают со вложенными циклами. В этом случае для каждого уровня используется свой ключ:
<?php
namespace AppLivewire;
use LivewireComponent;
class NestedList extends Component
{
public $data = [
[
'id' => 1,
'name' => 'Category 1',
'items' => [
['id' => 1, 'name' => 'Item 1'],
['id' => 2, 'name' => 'Item 2'],
],
],
[
'id' => 2,
'name' => 'Category 2',
'items' => [
['id' => 3, 'name' => 'Item 3'],
['id' => 4, 'name' => 'Item 4'],
],
],
];
public function render()
{
return view('livewire.nested-list');
}
}
?>
<div>
@foreach ($data as $category)
<div wire:key="{{ $category['id'] }}">
<h3>{{ $category['name'] }}</h3>
@foreach ($category['items'] as $item)
<div wire:key="{{ $item['id'] }}">
{{ $item['name'] }}
</div>
@endforeach
</div>
@endforeach
</div>
Результат выполнения кода:
<div>
<div>
<h3>Category 1</h3>
<div>Item 1</div>
<div>Item 2</div>
</div>
<div>
<h3>Category 2</h3>
<div>Item 3</div>
<div>Item 4</div>
</div>
</div>
Пример
Если элементы коллекции не имеют уникального идентификатора, можно использовать сам элемент или индекс цикла. Однако это менее эффективно, так как Livewire не сможет точно идентифицировать элемент при изменениях:
<div>
@foreach ($items as $index => $item)
<div wire:key="{{ $index }}">
{{ $item }}
</div>
@endforeach
</div>
В этом случае при удалении или добавлении элементов Livewire может пересоздавать соседние элементы, что снижает производительность.