Приветствую всех поклонников Laravel!
Эта статья-обзор новой, уже третьей версии Livewire. Решил сделать эту статью после выпуска на youtube-канале видео обзора Livewire, который понравился аудитории. Для тех, кто больше любит видео, то оно тут:
Ну и заодно также взглянем на новинку - Volt. Думаю, многие из вас ждали этот обзор и особенно обзор Volt.
Документация
Первое отличие - документация 3 версии Livewire переехала на поддомен laravel.com. Это https://livewire.laravel.com/ и заодно обновили дизайн.
![](https://habrastorage.org/getpro/habr/upload_files/08c/94b/9f3/08c94b9f358dc2eb6160648a81f0c52f.png)
Установка
Перейдем в документацию https://livewire.laravel.com/docs/quickstart в раздел установки.
![](https://habrastorage.org/getpro/habr/upload_files/9d6/da0/92b/9d6da092bf2be2c2cc8af010d2368a14.png)
Установка сильно упростилась и теперь зависимости устанавливаются с помощью композера:
composer require livewire/livewire
Следующий шаг - это публикация config:
php artisan livewire:publish --config
На этом всё, друзья. Теперь в основной шаблон не нужно добавлять @livewireStyles
и @livewireScripts
. Livewire будет делать инъекцию этих скриптов и стилей автоматически.
![](https://habrastorage.org/getpro/habr/upload_files/187/f6c/7e0/187f6c7e0f1b3913768f2a5dc6de7992.png)
Но если вдруг Вам такой подход не нравится, то в config можете переключить false и добавлять ассеты самостоятельно, по старинке:
'inject_assets' => false,
Прежде чем мы пойдем далее, сразу скажу о понравившемся мне моменте - теперь wire:model
по умолчанию с параметром defer
. И это круто, так как до этого каждый раз, объявляя wire:model
, приходилось добавлять .defer
. Так как апдейт на каждое изменение практически никогда не был нужен (или только в редких случаях). Но теперь для этих редких случаев уже нам потребуется определенные параметры как live
, либо blur
.
![](https://habrastorage.org/getpro/habr/upload_files/0ed/939/330/0ed9393306f1f224bda910bd833f743d.png)
Wire:Navigate
Чтобы подготовить для вас этот обзор как можно более качественнее, я заодно начал реализацию проекта из экосистемы CutCode с готовыми Livewire компонентами, но уже на Livewire 3 и Volt. Как раз на примере этого проекта мы будем с вами играться.
![](https://habrastorage.org/getpro/habr/upload_files/777/0f1/b2b/7770f1b2ba53e3c341644bf6dee1ae65.png)
Итак, следующее на что стоит обратить внимание в Livewire 3 - это новая фича wire:navigate
, мы можем ставить этот параметр на ссылке и у нас будет переход по страницам без перезагрузки:
![](https://habrastorage.org/getpro/habr/upload_files/433/7a9/3f4/4337a93f40ae289a35acb2c6e4dcfdf1.png)
На самом деле ничего сверхъестественного нет, попытка эмуляции single page application. Как видим у меня на логотипе стоит wire:navigate
:
![](https://habrastorage.org/getpro/habr/upload_files/e80/393/182/e803931825ffd82cfe0f3eca36410c86.png)
Если мы с вами по нему нажмем, то у нас перезагрузки не будет, но при этом придет HTML и основная страница заменится. Есть еще определенный интересный модификатор - называется он wire:navigate.hover
:
![](https://habrastorage.org/getpro/habr/upload_files/838/2c7/160/8382c7160d2593b8334fd3e862eb51b3.png)
В этом случае у нас с вами HTML-содержимое страницы придет без клика а просто при наведении.
Forms
Далее важное изменение - это Forms (формы). Классы с формами и все что касается форм теперь вынесено в отдельный слой.
![](https://habrastorage.org/getpro/habr/upload_files/abf/0d7/da9/abf0d7da990619fd9a7eb92ca18410af.png)
У некоторых возникли вопросы из-за того что старый подход с Model binding теперь не подходит. Давайте взглянем на Upgrade Guide и перейдем в секцию Eloquent model binding и ранее в Livewire компоненте нам было достаточно указать свойства и сделать type hint модели и далее черезwire:model
, через точку, обращаться к полям этой модели.
![](https://habrastorage.org/getpro/habr/upload_files/838/169/ca9/838169ca9e5e81d558ddc4114eba3032.png)
Теперь так работать не будет. Так как эту логику необходимо выносить Form Objects, о которых мы сейчас с вами поговорим. Но, если вы хотите работать по старинке, то в конфиге вы можете переключить флаг
'legacy_model_binding' => true,
и старый подход будет работать. Но я не рекомендую вам его использовать и предлагаю переходить на новую концепцию. Рано или поздно этот legacy подход отключат.
Вернемся к формам.
![](https://habrastorage.org/getpro/habr/upload_files/ae3/972/fd1/ae3972fd18370a69b8a24f449b05a8a9.png)
Попробуем создать форму, используя artisan команду из документации.
php artisan livewire:form UserForm
И давайте также создадим компонент, где будем с вами эту форму юзать:
![](https://habrastorage.org/getpro/habr/upload_files/f31/69b/4fa/f3169b4fabaad94935a52df7e94216b3.png)
Давайте откроем созданный компонент. Пока что пустой:
![](https://habrastorage.org/getpro/habr/upload_files/0d7/529/2f2/0d75292f25b378cd481d46bb4aeb84c6.png)
Чтобы нам не тратить время на Blade, скопируем код формы из документации:
![](https://habrastorage.org/getpro/habr/upload_files/06c/74a/d0f/06c74ad0f244c5c6fa7c9a94ec678372.png)
Вставляем в наш user.blade.php
:
![](https://habrastorage.org/getpro/habr/upload_files/898/3d6/993/8983d699364519cf1a5d5b3f30286cc9.png)
Новая особенность Livewire 3 - у формы не нужно по умолчанию указывать prevent
, это будет по дефолту (так же как с wire:model
- теперь не нужно по умолчанию указывать defer
).
Как видим, в данном случае ничего у нас не изменилось. Только появилась определенная форма, с которой мы сейчас будем играться. Давайте оживим немного форму и в коде который мы скопировали из документации изменим form.title
на form.name
и form.content
на form.email
:
![](https://habrastorage.org/getpro/habr/upload_files/7d5/c69/683/7d5c69683281afa5f5715dff34d7eb65.png)
Далее, друзья, давайте смотреть на изменения. Во-первых livewire компоненты и форма теперь у нас располагаются в директории app, а не в http.
![](https://habrastorage.org/getpro/habr/upload_files/da9/ef8/7d7/da9ef87d71f91fb02ebe5623c2dc313b.png)
Формы в директории Forms, а компоненты соответственно в директории Livewire. Вот наш компонент User:
![](https://habrastorage.org/getpro/habr/upload_files/897/f07/ba3/897f07ba3cce70d9935e191a168851d5.png)
Как мы бы действовали с вами ранее, когда еще никаких форм не было? Верно, мы бы прямо здесь (в User.php) с вами создавали свойства. Если бы использовали Legacy подход, то сделали бы type hint c моделью и все было бы хорошо.
![](https://habrastorage.org/getpro/habr/upload_files/194/25f/dd8/19425fdd8b6469631f90e2604d93c54b.png)
Но давайте сделаем как положено, на отдельных свойствах - $name
и $email
:
![](https://habrastorage.org/getpro/habr/upload_files/e00/0c9/906/e000c9906225a62602e76d15d08ed914.png)
В старой версии Livewire мы в User.php
сделали бы метод Save, затем добавили валидацию и указали бы правила. После этого - создаем пользователя (User::create
), передав ему name и email:
![](https://habrastorage.org/getpro/habr/upload_files/b7b/a6f/ad4/b7ba6fad441e1d8b11c69a157533fe7f.png)
Но, друзья, с приходом форм мы просто переносим эту логику и ответственность на сами формы давайте это сделаем и перенесем часть кода в наш UserForm.php
:
![](https://habrastorage.org/getpro/habr/upload_files/01e/c7d/8d3/01ec7d8d3b4ddd0fab2c6ace9db6b621.png)
соответственно validate
из User.php
так же уберем:
![](https://habrastorage.org/getpro/habr/upload_files/bff/65c/14a/bff65c14a98f2d2ef984763d781fcf81.png)
В самой форме мы можем использовать как и по старинке наши правила - rules
:
![](https://habrastorage.org/getpro/habr/upload_files/739/ae9/fbc/739ae9fbc09c65df12a4d05302c1763d.png)
В целом, форма готова. Далее мы просто объявляем публичное свойство public UserForm $form
а в методе save()
указываем $this->form->validate
:
![](https://habrastorage.org/getpro/habr/upload_files/996/990/b97/996990b971243a4ef33793c3fe85ce4e.png)
Но мы можем сделать еще лучше и вынесем логику в форму:
![](https://habrastorage.org/getpro/habr/upload_files/03b/d0b/287/03bd0b28712ed9a387d56713596dd6a6.png)
А в самом компоненте у нас будет $this->form->storе()
:
![](https://habrastorage.org/getpro/habr/upload_files/742/6bd/965/7426bd965498f231b4e45deb475c6c5e.png)
Давайте выведем компонент в app.blade.php
, чтобы было на что посмотреть:
![](https://habrastorage.org/getpro/habr/upload_files/2c2/14d/005/2c214d005425a9a656ebf5583cdb020b.png)
Вернемся на главную страницу, видим, что у нас образовалась форма
![](https://habrastorage.org/getpro/habr/upload_files/b9c/84d/77e/b9c84d77ed575ac31da78649835dc472.png)
Нажмем Save и видим, что у нас срабатывает валидация!
![](https://habrastorage.org/getpro/habr/upload_files/2e7/33b/52a/2e733b52a2bd14608ecc59a66969dad3.png)
Мы вынесли логику в форму и у нас все работает как положено.Чтобы форма выглядела по приятнее навел немного красоты:
![](https://habrastorage.org/getpro/habr/upload_files/e36/b42/5c1/e36b425c198e14170f5ff9408433e579.png)
Следующий вопрос - это как биндить модель в эту форму? Раньше мы просто биндели в компонент, делали type hint определенного свойства и далее через точку делали wire:model
уже внутри компонента.
C формой дела обстоят немного иначе - это частый вопрос при переходе на третью версию. Давайте его с Вами рассмотрим. Откроем User.php
и добавим по старинке метод mount()
. Укажем, что у нас обязательный параметр модель User (\App\Models\User $user
).
Давайте в форме сделаем метод setUser(User $user)
и внутри наполним данными name и email для наглядности:
![](https://habrastorage.org/getpro/habr/upload_files/0f7/716/63c/0f771663cc719f89295e97bc9eeb4472.png)
А далее нам нужно ее установить (засетить) форму, то есть сделать $this->form->setUser ($user)
![](https://habrastorage.org/getpro/habr/upload_files/4d2/be8/7bd/4d2be87bdd0860aa2f2e9fc10171f182.png)
Далее открываем app.blade.php
(там, где мы рендерим компонент) и добавляем livewire:user
:
![](https://habrastorage.org/getpro/habr/upload_files/869/82e/424/86982e4241d3020fcbcbc18cb7fed595.png)
Давайте посмотрим, что у нас из этого получилось. Видим что у нас бинд срабатывает и данные подставляются:
![](https://habrastorage.org/getpro/habr/upload_files/fb8/b88/9ea/fb8b889ea0e503cc6e6061da7cf10f1b.png)
Теперь если очистим нажмем save, видим, что и валидация у нас работает:
![](https://habrastorage.org/getpro/habr/upload_files/0c3/3eb/5fc/0c33eb5fc6258ec1e3b946886145d458.png)
PHP attributes
Дальше вопрос валидации. Здесь есть некоторые изменения - старый подход через методы rules()
, messages()
работает, но также для нашего удобства добавили PHP атрибуты. Да Livewire просто пестрит PHP атрибутами, они практически везде и сейчас постепенно мы их с вами будем осваивать.
Давайте уберем пока что метод rules()
из UserForm.php
и далее с помощью атрибута Rule
из Livewire будем добавлять необходимые нам правила - required, string и min со значением 3. То же самое продублируем и на e-mail:
![](https://habrastorage.org/getpro/habr/upload_files/11a/061/e66/11a061e669861277fdae0550b05c25b4.png)
Вернемся в браузер, обновляемся, попробуем очистить поля, нажмем save и видим что у нас все так же работает только теперь через PHP атрибуты.
![](https://habrastorage.org/getpro/habr/upload_files/bdf/6a7/17c/bdf6a717c7b4a257dfcf70dcfdce4711.png)
Добавлять атрибуты можно другим способом, Вы можете перейти в раздел валидация и более углубленно взглянуть на те возможности, которые дают нам PHP атрибуты. Есть дополнительные свойства, прямо в атрибуте можно указать и сообщения валидации, а также переводить сообщения или нет, можно указывать в виде массива, добавлять туда классы. Подход через PHP attributes присутствует, и если он вам больше нравится, то обязательно используйте. Если нет, то можете пользоваться старым подходом через rules(): array
:
![](https://habrastorage.org/getpro/habr/upload_files/10a/335/b0e/10a335b0ec63d69e8c04f7e4896bb59c.png)
Кстати, большинство новичков ищут в документации что-либо о Form Requests. У нас есть форма и хочется в ней применять стандартные Form Requests, но если вы пройдетесь по документации Livewire, то вы не увидите ни одного слова о Form Requests. Но если вдруг вы хотите их использовать, то можете их интегрировать прямо в метод rules()
.
Давайте создадим какой-либо Form Requests, так как в проекте который используется для примера их нет.
![](https://habrastorage.org/getpro/habr/upload_files/79b/9db/671/79b9db67132e05c50f8c4d9a3d3d740d.png)
И если бы я хотел интегрировать сюда в Form Requests, я бы сделал следующее и в целом это рабочий подход для решения.
![](https://habrastorage.org/getpro/habr/upload_files/020/d26/245/020d26245dd7a12aa0af653c25ad3fe2.png)
Друзья, раз уж мы с вами затронули тему PHP атрибутов в Livewire, то давайте ее продолжим и посмотрим еще на несколько таких атрибутов. Для этого переместимся в компонент для главной страницы (Home.php
), здесь full page компоненты и поэтому я прямо в компоненте могу с помощью PHP атрибутов задавать title страницы, менять layout. Как это делается? Например, у метода render()
я могу добавить атрибут title и указать что-либо (Hello):
![](https://habrastorage.org/getpro/habr/upload_files/39c/358/aa8/39c358aa88fcb50aa9cb4384485b90d6.png)
Давайте вернемся назад, обновимся и видим, что заголовок поменялся на тот который я указал:
![](https://habrastorage.org/getpro/habr/upload_files/c01/485/d91/c01485d91dc53b1d80c213093d0b91dc.png)
Тоже самое можно было бы сделать не у метода render()
, а у класса Home и все так же будет работать:
![](https://habrastorage.org/getpro/habr/upload_files/27f/3d1/933/27f3d1933134353fb333458061600506.png)
И в таком же стиле я могу менять layout, используя атрибут Layout где указываем его расположение и это будет работать.
![](https://habrastorage.org/getpro/habr/upload_files/bd0/fa2/492/bd0fa2492b4a7757e8854300b0406ea7.png)
Давайте сделаем ошибку, чтобы убедиться что действительно работает - укажем components.layouts.app2
- такого layout уже нет и получаем соответствующее уведомление об ошибке:
![](https://habrastorage.org/getpro/habr/upload_files/d62/2fe/a61/d622fea6114c69d3ec82998fadfba034.png)
Следующий интересный атрибут - Locked, давайте посмотрим как он выглядит и как он работает. На определенное свойство мы можем его с вами повесить и далее в клиентской части уже не сможем его изменять.Давайте попробуем и повесим его на поле для ввод имени пользователя, попытаемся изменить (что-либо ввести в поле) нажимаю Save и у меня появляется исключение - что Locked Property мы менять с вами не можем.
![](https://habrastorage.org/getpro/habr/upload_files/d6e/2ac/ede/d6e2acede237a09656cd4cb6c65456a8.png)
События
Друзья, следующее что мы с вами рассмотрим - это события (events) и как по мне с атрибутами это супер интересный подход. Давайте взглянем как это работает? К примеру во время сохранения (User.php
) мы с вами будем вызывать событие, пусть это будет form-store
. Закомментируем 22 строку и добавим метод onFormStore()
в котором для наглядности и простоты сделаем Dump and Die (dd). Теперь укажем через атрибут On на какое событие будет вызываться этот метод, соответственно form-store
. То есть в методе save()
события дергаем, а в onFormStore()
указываем какое (событие) будет при этом вызываться.
И таких listener может быть несколько.
![](https://habrastorage.org/getpro/habr/upload_files/f24/538/c6a/f24538c6a040980550d79d7bf9df6f8f.png)
Проверим в браузере, нажимаем на save и видим что dump & die срабатывает:
![](https://habrastorage.org/getpro/habr/upload_files/ba7/af4/c12/ba7af4c12f5c6cd2e605057880c8b3fe.png)
Мы даже с вами можем взять метод onFormStore()
из User.php
и вынести его в какой-то другой компонент, например разместим на главной странице Home.php
. Проверим в браузере - событие снова вызовется.
Также интересный атрибут, когда мы дергаем какой-либо метод из Blade компонента, то у нас происходит ReRender. Приходят данные и компонент рендерится по-новому. Если на определенные методы такое поведение нам необходимо исключить, то мы можем добавить атрибут Renderless и в таком случае, когда мы будем дергать этот метод, компонент перерисовываться не будет:
![](https://habrastorage.org/getpro/habr/upload_files/5f9/816/948/5f9816948f65c60a200defc86ca4deef.png)
Вычисляемые свойства
Следующий интересный раздел в Livewire 3 - это computed properties, вычисляемые свойства. Необходимы они нам для контроля над производительностью. Если мы вешаем атрибут Computed над каким-то методом, то он нам уже будет доступен через $this->
внутри этого компонента и внутри Blade-компонента. Но при этом в процессе реквеста вызываться он будет только единожды:
![](https://habrastorage.org/getpro/habr/upload_files/985/84c/384/98584c384765c9a71f5b02d590ac5494.png)
Независимо от того, что у нас здесь запрос к базе, livewire закэширует содержимое и мы при неоднократном обращении к одному и тому же методу будем всегда возвращать одно и то же значение. Давайте взглянем как это работает? Будем использовать компонент User.php
, создадим свойство u()
и добавим ему компонент [Computed], а в содержании укажем о возвращении рандомного юзера. И давайте пару раз задампим его. Во-первых в методе render()
указанном в User.php
, здесь обратите внимание свойства не создавалось, но обращение как к свойству u.
![](https://habrastorage.org/getpro/habr/upload_files/dcc/b1e/a96/dccb1ea96177a1a89973a54d9bcc85a8.png)
Во-вторых, то же самое в blade-компоненте user.blade.php
. Также обращаю ваше внимание на то, что в blade-компоненте мы также вызываем через $this->
:
![](https://habrastorage.org/getpro/habr/upload_files/09b/8c0/fab/09b8c0fabbd03f9f25d249871b5e0de1.png)
Как видите в компоненте мы вызываем id пользователя и тоже самое внутри Blade шаблона. Но при этом, отправляем всего один request цикл, один запрос:
![](https://habrastorage.org/getpro/habr/upload_files/2b7/d81/ec5/2b7d81ec5952e2cdd57611f3fca07ffd.png)
Также мы можем дополнительно кэшировать, указав в computed cache:true
:
![](https://habrastorage.org/getpro/habr/upload_files/bcd/feb/f19/bcdfebf19fa819a70baebadae2662fe6.png)
Проверим. При каждом обновлении будет приходить id первого пользователя:
![](https://habrastorage.org/getpro/habr/upload_files/495/037/23e/49503723e584b6405310c05b05c14381.png)
Вложенные компоненты
Передвигаемся в более интересную тему это вложенные компоненты (nesting components). По сути полностью переписанный подход в Livewire 3 и теперь он работает намного круче и есть реактивность. Давайте взглянем на практике - создадим еще один с вами компонент, который будет у нас внутри компонента User. Давайте назовем его UserInner
:
![](https://habrastorage.org/getpro/habr/upload_files/5a8/939/57c/5a893957c72e110e53a3af8412e73553.png)
Сразу его откроем и вызовем его в нашем компоненте user.blade.php
, как раз он станет у нас вложенным и сразу давайте передадим в него форму:
![](https://habrastorage.org/getpro/habr/upload_files/cac/24b/04f/cac24b04f435f9d95907907b8dc44232.png)
Откроем UserInner.php
и создадим метод mount()
:
![](https://habrastorage.org/getpro/habr/upload_files/666/fc5/808/666fc58088cfedcd3058edc68f941c9c.png)
Давайте откроем view user-inner.blade.php
и в ней соответственно выведем что-то из формы, например name и заодно сразу добавим Input, чтобы добавить wire:model
:
![](https://habrastorage.org/getpro/habr/upload_files/a50/69a/de1/a5069ade15c0dac18169a0e72a326062.png)
Посмотрим в браузере что у нас при этом получается. Обновляемся, и видим, что у нас есть родительская форма и есть дочерняя:
![](https://habrastorage.org/getpro/habr/upload_files/b98/0b2/b4b/b980b2b4bacb35693a26bb34e8ef80ef.png)
И давайте заодно добавим кое-что в родительское поле. Укажем, что у нас wire:model.live
- чтобы при вводе сразу менялась свойство формы:
![](https://habrastorage.org/getpro/habr/upload_files/a4a/477/db8/a4a477db8d593c6d2f2cfb0d99e3b68e.png)
Возвращаемся в браузер и меняем содержимое поля. Видим что у нас в родительском компоненте значение изменяется, но при этом в дочернем ничего не меняется:
![](https://habrastorage.org/getpro/habr/upload_files/336/0d7/03f/3360d703f2a0972793ceb6f0eb96ef5e.png)
Так работал Livewire раньше, никакой реактивности не было. У нас рендерился только родительский компонент. Давайте заодно взглянем на запросы, которые у нас отправляются. Если мы с вами будем менять содержимое родительского поля,
![](https://habrastorage.org/getpro/habr/upload_files/67c/a3f/b82/67ca3fb82cd26ecab9f797743ae6e1a7.png)
Видим что уходит апдейт и у нас только один компонент изменяется и приходит только его HTML:
![](https://habrastorage.org/getpro/habr/upload_files/d66/0b2/b8c/d660b2b8c534b40d0006ae6ac1e0afcf.png)
Чтобы менять и дочерние, добавить реактивности которую мы ожидаем, нам нужно с вами перейти в UserInner.php
и на форму повесить атрибут [Reactive]. Возвращаемся в браузер, обновляемся и теперь при вводе значений в поля формы у нас меняется и содержимое дочернего поля и его wire:model
и значение:
![](https://habrastorage.org/getpro/habr/upload_files/8ba/8e6/7f9/8ba8e67f93af1b768a398c6003c029a6.png)
Посмотрим в инструментах разработчика на вкладу Network, что там происходит. При вводе в родительское поле видим, что в update у нас массив с двумя компонентами - и родитель и все его дочерние:
![](https://habrastorage.org/getpro/habr/upload_files/885/0c0/a14/8850c0a14ad8b9a08111097ff06349c0.png)
И напоследок еще немного магии по вложенным компонентам. Нам также доступна переменная $parent
с помощью которой мы можем обратиться к объекту родительского компонента. Давайте попробуем:$parent->form->name
![](https://habrastorage.org/getpro/habr/upload_files/268/285/89d/26828589d42037643b22ac18e8efba25.png)
Смотрим в браузере - вводим значения в поле родительской формы и это же значение появляется и в дочерней. Работает!
![](https://habrastorage.org/getpro/habr/upload_files/110/138/584/11013858470fec88da81fdde13047503.png)
Polling
Друзья, также хочу вам показать раздел polling
и wire:poll
который был и до этого. Многие думают, что у нас происходит живое обновление по типу веб-сокетов. Даже в документации написано технология как web-сокеты, но ничего общего с веб-сокетами это не имеет. Конечно штука интересная, но в ней нет ничего необычного. На самом деле это просто запросы по тайм-ауту, поэтому рекомендую относиться к этой директиве крайне аккуратно. Давайте добавим на компонент user-inner.blade.php wire:poll:
Посмотрим в браузере, на вкладку Network инструментов разработчика:
![](https://habrastorage.org/getpro/habr/upload_files/f9b/3a2/064/f9b3a2064af94782e9cdc7249a650f19.png)
Как видите по тайм-ауту происходит запрос, простой запрос, никакие не веб-сокеты и в ответе мы получаем данные по компоненту. Если что-то там на сервере изменилось, то само собой придут данные. Но обратите внимание как мы сейчас спамим запросами к серверу, поэтому крайне аккуратно относитесь к этой директиве. Если у вас их будет множество, все они будут спамить, решение будет не из лучших, а под капотом нет никакой магии, простой тайм-аут:
![](https://habrastorage.org/getpro/habr/upload_files/f71/005/de1/f71005de13f5e078f453367f9f14317f.png)
Lazy Components
Следующее что я хочу вам показать это крайне интересная фича, а именно Lazy компоненты - ленивые компоненты, которые сразу у нас не грузятся, а когда у нас уже пришел ответ, уже после этого отправляется запрос, не мешая нашему первому рендеру. Для этого достаточно добавить lazy:
![](https://habrastorage.org/getpro/habr/upload_files/459/fef/93f/459fef93f1c0432554494f93b4aff29c.png)
Представим, у нас есть какие-то компоненты, какие-то сложные метрики с множеством запросов. Не хочется чтобы наша страница грузилась несколько секунд перед тем как отдать ее пользователю. Мы добавляем lazy, а далее переходим в компонент и вешаем на него placeholder
. Это то, что у нас появится прежде чем мы запустим рендер компонента. И давайте чтобы посмотреть как это работает сделаем sleep
продолжительностью 3 секунды:
![](https://habrastorage.org/getpro/habr/upload_files/bdb/7dc/283/bdb7dc283485ef84a67c199bd9f57a4d.png)
Вернемся на в браузер и обновимся:
![](https://habrastorage.org/getpro/habr/upload_files/374/abb/ed9/374abbed91d30c974a2829bb2fb513db.png)
Видим, что второго компонента пока что нет, есть надпись “loading”, идёт загрузка и только по прошествию указанного времени (мы указали 3 сек.), появился наш дочерний элемент:
![](https://habrastorage.org/getpro/habr/upload_files/25d/779/101/25d77910107fde6fe6d4f982e08f9138.png)
Отличная штука обязательно берем на вооружение.
LiveWire Volt
Настало время для обзора Volt. На самом деле это тот же самый Livewire, он располагается в документации Livewire и создан на его основе. Единственное его отличие, что все находится в одном blade файле. Никакого Livewire класса, Livewire класс-компонента больше нет. И сверху в теге PHP мы организуем всю backend логику, а дальше у нас идет frontend. Разработчики вдохновлялись Vue Framework.
Устанавливается Volt просто, сперва устанавливаем Livewire, затем Volt. Делается это командой volt:Install
, которая добавляет сервис провайдер - VoltServiceProvider
.
Внутри мы указываем где у нас располагаются Livewire компоненты, где будут располагаться страница для Folio.
![](https://habrastorage.org/getpro/habr/upload_files/082/5ef/51f/0825ef51f37110901c73c631cab3602e.png)
Далее, чтобы создать компонент используем команду make:volt
и далее название, как make:livewire
, только ключевое слово volt. Во всем остальном обязательно изначально вам нужно знать livewire, а уже после использовать Volt. Все то же самое перекочевало сюда в виде функций-хелперов. Единственное с чем может быть замешательство - это то, что входные параметры передаются при помощи функции state. Если нам необходим какой-то экшен, то вызываем его анонимной функцией.
![](https://habrastorage.org/getpro/habr/upload_files/b4d/406/dcd/b4d406dcd6e67f755efa0793274fec8e.png)
Также нам говорят что в целом можем использовать и классы, но также сверху blade-файла, внутри . Как по мне - это выглядит крайне убого! Если на то что мы пишем логику прямо в Blade в целом в рамках Volt можно закрыть глаза на каких-то небольших компонентах, но добавлять анонимные классы, считаю что выглядит ужасно.
Окей, со state
мы разобрались. Если нам необходим метод Mount, то пользуемся функцией mount()
:
![](https://habrastorage.org/getpro/habr/upload_files/058/ddc/736/058ddc73669e092c82fc598066a95b9f.png)
Хотим изменить layout - пользуемся функцией layout()
:
![](https://habrastorage.org/getpro/habr/upload_files/501/e04/dc7/501e04dc7aefd6481e9fcb2a5940acdb.png)
Пользуемся функцией title для заголовка:
![](https://habrastorage.org/getpro/habr/upload_files/1b8/2c6/cf3/1b82c6cf32d825ee2ff25a8dcdeca1ca.png)
Как я говорил ранее все то же самое есть и здесь. Продолжим листать документацию и видим пример использования locked()
через state()
. Мы использовали его ранее:
![](https://habrastorage.org/getpro/habr/upload_files/647/e37/3d8/647e373d8687cc5da19ceb561eb47229.png)
То же самое с reactive, то же самое с computed. Это тот же самый Livewire, просто изменился подход. Все теперь организовывается в Blade-компоненте. Можем продолжать листать документацию до бесконечности и ничего нового мы с вами здесь не увидим “сахар”, “сахар”, “сахар” в виде дополнительных функций, которые делают в точности все то же самое, что мы делали в стандартном Livewire классе.
Давайте все же немного поиграемся и создадим с volt-компонент counter:
![](https://habrastorage.org/getpro/habr/upload_files/e8e/9f5/30d/e8e9f530d105895562fcabfa6a2ed332.png)
Отлично, видим что Blade компонент создан и больше ничего. Вот он так выглядит по дефолту:
![](https://habrastorage.org/getpro/habr/upload_files/de8/da1/3f7/de8da13f72b5072dbd4274ef88ba538e.png)
Дальше нам предлагается со всем этим взаимодействовать. Давайте создадим определенный state, пусть будет count и по дефолту сделаем 0. Давайте попробуем вывести. Насколько я помню необходимо использовать $this
.
![](https://habrastorage.org/getpro/habr/upload_files/87e/c19/b44/87ec19b4464dab9fdc672d4b9bee314f.png)
Вернемся в браузер, обновимся и видим нолик, это state и то значение, которое мы здесь задаем:
![](https://habrastorage.org/getpro/habr/upload_files/fab/9a3/e87/fab9a3e874f15b065c26bcc4e848d1d1.png)
Давайте также добавим Action. Пусть будет кнопка которая у нас будет инкрементировать этот счетчик count. Используем wire:click
. Добавим инкремент, чтобы создать экшен, достаточно создать переменную которая у нас будет анонимная функция. На самом деле уже понимаю, что не очень удобно работать так как PHPStorm мне не подсказывает что в рамках $this->
контекста у нас есть count и приходится все писать самому:
![](https://habrastorage.org/getpro/habr/upload_files/f8d/636/1a0/f8d6361a009bd4f6726d6ee308654aaa.png)
Посмотрим в браузер, попробуем нажать в область отображения счетчика и видим что счетчик у нас меняется:
![](https://habrastorage.org/getpro/habr/upload_files/e2a/b97/fe6/e2ab97fe648b7175cf1b66044bbb9da8.png)
Давайте еще немного поиграем с Volt, заодно в очередной раз разберем тему computed properties - вычисляемых свойств, так как она мне очень нравится. Давайте создадим переменную $test
со значением computed(function())
, далее callback и внутри мы вернем count. И давайте выведем наш test, только он у нас computed:
![](https://habrastorage.org/getpro/habr/upload_files/a11/b6e/bd1/a11b6ebd17df47b4eb6fb950eb25bf53.png)
Вернемся в браузер, нажимаем на “+”, пытаемся инкрементировать. И первая переменная и вторая ведут себя абсолютно идентично:
![](https://habrastorage.org/getpro/habr/upload_files/69e/0d6/aa7/69e0d6aa7b14ee2062106b5f5a0f79fc.png)
Но давайте добавим computed метод persist
, который у нас будет кэшировать (запоминать):
![](https://habrastorage.org/getpro/habr/upload_files/cd3/f10/941/cd3f10941e22dc7eb075288a402ee66c.png)
Вернемся в браузер. При первом заходе у нас отображается значение 00, а дальше мы с вами инкрементируем, но computed теперь никак не меняется, так как это значение у нас закэшировано и повторно ничего не происходит:
![](https://habrastorage.org/getpro/habr/upload_files/58e/56f/722/58e56f7221ee51b0917420f39721be5b.png)
Давайте для наглядности изменим persist, добавив seconds и укажем чтобы он у нас хранился всего 2 секунды.
![](https://habrastorage.org/getpro/habr/upload_files/285/7f1/661/2857f1661dbe9ed6b49c96a054384c66.png)
Вернемся в браузер, обновимся, инкрементируем и видим, что не каждое изменение, но раз в 2 секунды у нас приходят измененные значения:
![](https://habrastorage.org/getpro/habr/upload_files/d56/eb6/29e/d56eb629ecc33152c1701c196bbebe27.png)
Друзья, как видите ковырять Volt мы можем с вами сколько угодно долго, но никаких отличий от Livewire, кроме подхода “все в одном blade-файле”, больше нет. В целом лично мне Livewire 3 дал так называемое второе дыхание, хочется что-то на нем написать, использовать, делать ролики на мой Youtube канал, но опять-таки только в том случае если и вам интересно. Поэтому обязательно напишите в комментариях стоит ли продолжать делать уроки по Livewire?
Спасибо за уделенное внимание. Данил Щуцкий, автор проекта CutCode.
Комментарии (4)
IgorAlentyev
18.12.2023 07:09Для фуллстеков на ларе лайвваер это прям топ тема для своих проектов, очень быстро работает и просто писать, разве что какую то совсем нетривиальную логику будет сложнее реализовать.
Bone
Мне всё равно кажется, что изучить vue проще, чем livewire
shasoftX
В данном случае автопроверки, как я понял, автоматом прикручиваются к странице. А на vue их придется прикреплять руками.
2medic
Есть и иные мнения, например здесь. Разработчик, наоборот, перенёс свои два рабочих проекта с Vue на Livewire, не потеряв ничего из того, что было нужно клиентам, при этом значительно упростив и ускорив тестирование.