Выпущена бета-версия Livewire v3
Переписанное ядро
Ядро Livewire было полностью переписано с нуля. Переписывание ядра было огромной работой, но это было необходимо для реализации всего того, что включено в данный релиз. Кроме того, новая архитектура ядра будет намного проще в поддержке для Калеба и участников проекта Livewire.
Использование Alpine
Ядро v3 теперь использует Alpine в полной мере. Вместо того чтобы включать код для применения обновлений DOM, добавления слушателей событий и т.д. в Livewire и Alpine, Livewire v3 использует Alpine для выполнения тяжёлой работы. Регистрируя Alpine-плагины, Livewire позволяет Alpine выполнять тяжёлую работу, обеспечивая при этом синтаксический сахар, который вы уже успели полюбить.
Это также означает, что Alpine теперь по умолчанию входит в состав Livewire, поэтому нет необходимости загружать Alpine через CDN или NPM. Он автоматически подключается.
Кроме того, в версии 3 для сравнения DOM и применения обновлений вместо morphdom используется плагин Alpine Morph. Это приведёт к уменьшению количества проблем с DOM-diffing и улучшению совместимости Livewire и Alpine.
Улучшена вложенность компонентов
В прошлом я считал вложенность компонентов Livewire антипаттерном или тем, чего следует избегать по возможности из-за потенциальных последствий для производительности. В версии 3 это уже не так!
Благодаря реактивным пропсам, пакетным запросам, новому свойству $parent
и другим улучшениям, в v3 значительно улучшена вложенность компонентов. Некоторые из этих улучшений мы рассмотрим более подробно далее в этой статье.
Улучшенная сериализация свойств
В v2 была предпринята попытка интеллектуально определить свойства типа при первоначальном рендере, чтобы при последующих запросах вернуть их к тем же типам. Однако v2 не поддерживала глубоко вложенную гидратацию. Если у вас есть коллекция со смешанными типами, v2 не сможет вернуть каждому элементу коллекции его исходный тип. v3 гораздо умнее в этом отношении и сохраняет тип каждого элемента, чтобы при последующих запросах вернуть их к правильным типам.
Пакетные запросы
В версии 2, когда несколько компонентов на странице опрашивали или прослушивали одно и то же событие, Livewire посылал отдельные запросы для каждого компонента каждый раз, когда ему требовалось связаться с сервером. Версия 3 гораздо более эффективна и объединяет все эти обновления в один запрос.
Улучшенные настройки по умолчанию
Инъекция маркера в Blade
Расхождение DOM — одна из наиболее распространённых проблем, с которой можно столкнуться в v2. Обычно эта проблема возникала из-за того, что @if
и аналогичные директивы Blade вставляли или удаляли элементы DOM. В v3 предпринята попытка обойти эти проблемы путём вставки HTML-комментариев (маркеров) в местах начала и окончания этих директив Blade. Ища эти маркеры, Livewire может сопоставить новые или удалённые элементы DOM с маркером, чтобы правильно разместить их в DOM.
<form wire:submit="save">
{{-- ... --}}
<!-- __BLOCK__ -->
@if ($success)
<div>Saved!</div>
@endif
<!-- ENDBLOCK -->
<div>
<button>Save</button>
</div>
<div>
wire:model
по умолчанию отложена
Изначально живой
Livewire был очень интересной функцией, поэтому его сделали по умолчанию. Поразмыслив и понаблюдав за реальным использованием, Калеб понял, что откладывать запросы wire:model
лучше по умолчанию. Большинство приложений не нуждаются в синхронизации вводимых значений с сервером при каждом нажатии клавиши, поэтому в v3 поведение по умолчанию изменилось. Прежняя функциональность wire:model.defer
стала новой по умолчанию при использовании wire:model
. wire:model.live
была добавлена для замены прежнего поведения по умолчанию для вводимых данных, которые действительно должны быть живыми
.
{{-- Теперь отложено по умолчанию --}}
<input wire:model="name">
{{-- Синхронизация с сервером при каждом нажатии клавиши --}}
<input wire:model.live="name">
Новые возможности
Автоматическое подключение ресурсов
В версии 3 Livewire автоматически внедряет свои стили, скрипты и Alpine. Больше нет необходимости добавлять <livewire:styles />
и <livewire:scripts />
или загружать Alpine в свои проекты!
Новое пространство имён по умолчанию
По умолчанию в v3 используется пространство имён App\Livewire
(и каталог app/Livewire
), а не App\Http\Livewire
. При желании можно настроить сохранение старого пространства имён.
Реактивные свойства
Некоторые пользователи Livewire, пришедшие из таких фронтенд-фреймворков, как React и Vue, автоматически предполагали, что свойства, которые они передают во вложенные компоненты, будут реагировать на изменения в родительском компоненте. В связи с некоторыми ограничениями в версии 2 это оказалось невозможным. Приходилось полагаться на события или другие обходные пути для синхронизации вложенных компонентов. В v3 добавлена поддержка "реактивных" пропсов. Это просто, как добавить атрибут #[Reactive]
PHP к свойству в классе компонента.
<?php
// ...
use Livewire\Attributes\Reactive;
class InvoiceItem extends Component
{
#[Reactive]
public $item;
}
Объекты форм
Объекты форм — это новая концепция, которая позволяет поддерживать чистоту классов компонентов за счёт абстрагирования части кода, специфичного для формы. Вы можете захотеть поместить свойства формы компонента, валидацию, функции сохранения и т.д. в объекты формы.
Здесь приведён небольшой пример, но я рекомендую прочитать документацию для получения полного списка возможностей!
<?php
namespace App\Livewire\Forms;
use Livewire\Form;
class UserForm extends Form
{
#[Rule('required')]
public $name = '';
#[Rule(['required', 'email'])]
public $email = '';
}
<?php
namespace App\Livewire;
use Livewire\Component;
use App\Models\Post;
use App\Livewire\Forms\UserForm;
class UpdateProfile extends Component
{
public UserForm $form;
public function save()
{
auth()->user()->update(
$this->form->all()
);
return $this->redirect('/profile');
}
public function render()
{
return view('livewire.update-profile');
}
}
<form wire:submit="save">
<input type="text" wire:model="form.name">
<div>
@error('form.name')
<span class="error">{{ $message }}</span>
@enderror
</div>
<input type="email" wire:model="form.email">
<div>
@error('form.email')
<span class="error">{{ $message }}</span>
@enderror
</div>
<button type="submit">Save</button>
</form>
wire:navigate
(режим SPA)
Ещё одно новое дополнение — wire:navigate
. При использовании полностраничных компонентов Livewire теперь можно добавлять к ссылкам атрибут wire:navigate
, что позволяет реализовать SPA-подобный опыт. Вместо загрузки всей страницы Livewire добавит индикатор загрузки в верхнюю часть страницы, получит содержимое новой страницы в фоновом режиме и затем интеллектуально подменит HTML на странице. Функция также поддерживает предварительную выборку и переадресацию, а также обеспечивает возможность работы с сохраняемыми элементами.
<a href="/profile" wire:navigate>Profile</a>
@persist
С добавлением wire:navigate
теперь можно иметь сохраняемые
элементы, которые не перезагружаются при переходе по различным страницам. Эта возможность будет полезна для таких случаев, как аудиоплееры, которые должны продолжать воспроизводить звук, пока пользователи переходят по разным страницам.
Чтобы воспользоваться этой возможностью, оберните элемент, который необходимо сохранить, директивой @persist
:
@persist('player')
<audio src="{{ $episode->file }}" controls></audio>
@endpersist
Лениво загружаемые компоненты
Livewire теперь поддерживает компоненты с ленивой загрузкой. Иногда бывает так, что компонент, который может замедлять начальную загрузку страницы или изначально скрыт в модальном окне, необходимо лениво загрузить, чтобы начальная загрузка страницы была быстрой.
Для ленивой загрузки компонента добавьте атрибут lazy
к компоненту в Blade.
<livewire:your-component lazy />
При первоначальной загрузке страницы Livewire пропустит рендеринг этого компонента. После загрузки всего остального содержимого страницы будет отправлен сетевой запрос на полный рендеринг компонента, и компонент будет вставлен в DOM.
Свойство $parent
Для взаимодействия с родительскими
компонентами в предыдущих версиях Livewire приходилось использовать события и слушатели. В версии 3 появилось новое свойство $parent
, которое можно использовать для вызова методов родительских компонентов непосредственно из дочерних.
<div>
<span>{{ $item->name }}</span>
<button wire:click="$parent.remove({{ $item->id }})">Remove</button>
</div>
Гибридные методы/запуск JS из бэкенда
В v3 появилась возможность писать JavaScript-методы в компонентах бэкенда. Добавив атрибут #[Js]
к методу компонента, вы можете написать JavaScript-код в виде строки, и Livewire откроет этот метод для вашего фронтенда. При вызове метода через wire:click
JavaScript будет выполняться на фронтенде без отправки сетевых запросов обратно на сервер.
<?php
// ...
use Livewire\Attributes\Js;
class UsersTable extends Component
{
public $filters = [];
#[Js]
public function reset()
{
return <<<'JS'
$wire.filters = [];
JS;
}
// ...
}
<div>
<div>
<input wire:model.live="filters.active" type="checkbox">
<label>Only active</label>
</div>
<button wire:click="reset">Reset Filters</button>
@foreach ($users as $user)
{{-- ... --}}
@endforeach
</div>
Иногда полезно выполнять небольшие фрагменты JavaScript из методов бэкенда. В v3 это можно сделать с помощью метода $this->js()
. Просто вызовите этот метод и передайте строку JavaScript, и Livewire выполнит её на фронтенде при следующем рендере.
public function save()
{
// ...
$this->js("alert('Вы только что выполнили JS из бэкенда!')");
}
Использование PHP-атрибутов
Атрибуты PHP являются относительно новой и мощной функцией PHP, и в Livewire v3 они активно используются в новых и существующих функциях.
#[Url]
Новый атрибут #[Url]
заменяет свойство $query
из v2. Добавьте #[Url]
над любым свойством компонента, и оно будет отслеживаться в строке запроса.
<?php
// ...
use Livewire\Attributes\Url;
class UsersTable extends Component
{
#[Url]
public $filters = [];
// ...
}
#[On]
Новый атрибут #[On]
заменяет свойство $listeners
из v2. Добавьте #[On('some-event')]
над методом вашего компонента, и он будет выполняться при каждом событии.
<?php
// ...
use Livewire\Attributes\Url;
class UsersTable extends Component
{
// ...
#[On('filters-reset')]
public function resetFilters()
{
// ...
}
}
#[Layout]
и #[Title]
Новые атрибуты #[Layout]
и #[Title]
позволяют задавать вид макета и заголовок для полностраничных компонентов. Они могут быть добавлены в метод рендеринга компонента или в сам класс.
#[Layout('layouts.app')]
public function render()
{
return view('livewire.create-post');
}
#[Computed]
На смену синтаксису getSomeProperty
в v2 для вычисляемых свойств пришёл атрибут #[Computed]
. Он функционирует так же, как и старый синтаксис, но имеет несколько новых, действительно мощных дополнений.
В v2 вычисляемые свойства можно было кэшировать только при одном запросе. В v3 свойство можно кэшировать при нескольких запросах и даже в разных компонентах. Это позволит легко кэшировать дорогостоящие запросы к базе данных!
use Livewire\Attributes\Computed;
// Кэширование по всем запросам
#[Computed(persist: true)]
public function user()
{
return User::findOrFail($this->userId);
}
// Кэш для всех экземпляров этого компонента
#[Computed(cache: true)]
public function user()
{
return User::findOrFail($this->userId);
}
#[Rule]
Новый атрибут #[Rule]
заменяет свойство $rules
и метод rules
из v2. Добавьте #[Rule(['required', 'max:150'])]
к свойству вашего компонента, чтобы указать Livewire, как должно проверяться это свойство.
<?php
// ...
use Livewire\Attributes\Rule;
class InvoiceItem extends Component
{
#[Rule(['required', 'max:120'])]
public $itemName;
// ...
}
#[Locked]
Новый атрибут #[Locked]
позволяет запретить пользователю обновлять свойство во фронтенде. Это можно использовать в качестве меры безопасности для свойств, которые пользователи не должны иметь возможности изменять.
<?php
// ...
use Livewire\Attributes\Locked;
class InvoiceItem extends Component
{
#[Locked]
public $id;
// ...
}
Обновление
Процесс обновления для большинства приложений будет довольно быстрым. В бета-версию включена команда livewire:upgrade artisan, которая поможет справиться с некоторыми более трудоёмкими изменениями, а затем вы можете следовать руководству по обновлению, чтобы убедиться, что все обновления актуальны.
Если вы предпочитаете доверить обновление Livewire специалистам, мы с Калебом предлагаем услугу, которая поможет вам ускорить процесс обновления. Ознакомиться с ней можно здесь.
Новый дизайн сайта и домен
В дополнение ко всем новым функциям и улучшениям, сайт документации Livewire был полностью переработан, перестроен и переписан!
Новая документация гораздо более подробна, чем документация v2. В них подробно рассматривается каждая функция и подробно описывается, как Livewire работает с гидратацией, морфингом и вложенными компонентами. Я настоятельно рекомендую прочитать весь сайт, если у вас есть время. Это мастер-класс по созданию приложений Livewire v3!
Ещё одно важное объявление — сайт документации переносится на livewire.laravel.com. Перейдите туда и ознакомьтесь с ним!
Это длинное сообщение, но в нем так много новых возможностей! Я надеюсь, что вы попробуете v3 в ближайшее время и не стесняйтесь оставлять свои отзывы об улучшениях.