Що нового в Livewire 4

0
Перекладено ШІ
Оригінал: Laravel News
Оновлено: 15 січня, 2026
Livewire 4 перевертає підхід до компонентів — вони тепер за замовчуванням однофайлові й можуть містити вбудований JavaScript та CSS. Islands, оптимістичний UI, drag‑and‑drop та нові API роблять створення швидких реактивних інтерфейсів простішим і продуктивнішим.

Livewire 4 нарешті тут — і це найбільший реліз.

Йдеться не про ускладнення — а про кращі значення за замовчуванням, менше перешкод та потужніші інструменти для створення саме того, що ви хочете. Ми місяцями переосмислювали, якими мають бути Livewire-компоненти, і пишаємося результатом.

Поглянемо.

# Компоненти на основі view

Найпомітніша зміна в Livewire 4 — підхід до написання компонентів. Замість постійного перемикання між PHP-класом і Blade-файлом тепер усе можна тримати в одному файлі:

<?php // resources/views/components/⚡counter.blade.php
 
use Livewire\Component;
 
new class extends Component {
    public $count = 0;
 
    public function increment()
    {
        $this->count++;
    }
};
?>
 
<div>
    <h1>{{ $count }}</h1>
    <button wire:click="increment">+</button>
</div>
 
<style>
    /* Scoped CSS... */
</style>
 
<script>
    /* Component JavaScript... */
</script>

Цей формат тепер за замовчуванням при запуску php artisan make:livewire. Емодзі блискавки робить Livewire-компоненти помітними в файловій структурі — зразу видно, що це Livewire, а не звичайний Blade-компонент. (Емодзі можна відключити, якщо не до вподоби.)

Для великих компонентів є й багатофайловий формат, який групує все в одній директорії:

⚡counter/
├── counter.php
├── counter.blade.php
├── counter.css          (optional)
├── counter.js           (optional)
└── counter.test.php     (optional)

Створити такий можна з --mfc, а конвертувати формати — командою php artisan livewire:convert.

# Маршрути

Посилайтеся на компоненти однаково всюди. Livewire 4 вводить Route::livewire():

// Before (v3) - Still supported
Route::get('/posts/create', CreatePost::class);
 
// After (v4)
Route::livewire('/posts/create', 'pages::post.create');

Новий синтаксис звертається до компонентів за іменем, а не за класом. Це узгоджується зі способом рендерингу компонентів у вашому додатку.

# Простори імен

Livewire тепер пропонує рекомендації щодо структури додатку. За замовчуванням доступні два простори імен: pages:: для сторінкових компонентів і layouts:: для layout'ів — усе інше розміщується в resources/views/components поруч із Blade-компонентами.

Route::livewire('/dashboard', 'pages::dashboard');

У модульних додатках можна реєструвати власні простори імен: згрупуйте адмін-компоненти під admin::, білінг — під billing:: або як вам зручніше для архітектури.

# Скрипти та стилі

JavaScript і CSS компонента тепер живуть поруч із ним. Додавайте <script> і <style> безпосередньо в шаблон:

<div>
    <h1 class="title">{{ $count }}</h1>
    <button wire:click="$js.celebrate">+</button>
</div>
 
<style>
.title {
    color: blue;
    font-size: 2rem;
}
</style>
 
<script>
    this.$js.celebrate = () => {
        confetti()
    }
</script>

Стилі автоматично scoped до компонента — ваш клас .title не «витече» в інші частини сторінки. Потрібні глобальні стилі? Додайте атрибут global: <style global>.

Скрипти мають доступ до this як контексту компонента — це псевдонім для $wire, до якого ви звикли.

Обидва віддаються в браузер як звичайні .js/.css-файли й автоматично кешуються для оптимальної продуктивності.

# Islands

Islands — головна фіча Livewire 4. Вони дозволяють створювати ізольовані області всередині компонента, які оновлюються незалежно одна від одної:

<div>
    @island
        <div>
            Revenue: {{ $this->revenue }}
            <button wire:click="$refresh">Refresh</button>
        </div>
    @endisland
 
    <div>
        <!-- This won't re-render when the island updates -->
        Other content...
    </div>
</div>

При натисканні «Refresh» перевідренерується лише island — решта залишиться незмінною. Раніше для подібної ізоляції доводилося виносити частину в дочірній компонент і працювати з props та events.

Переваги продуктивності не обмежуються лише DOM-оновленнями. У поєднанні з computed properties підвантажуються лише ті дані, які потрібні конкретному island. Якщо компонент має три islands, кожен із різними computed, оновлення одного запускає тільки відповідні запити — ви ізолюєте навантаження від бази даних аж до відрендереного HTML.

Islands підтримують lazy loading (lazy: true), іменування для таргетингу між компонентами (name: 'revenue') і додавання контенту для infinite scroll:

<button wire:click="loadMore" wire:island.append="feed">
    Load more
</button>

# Slots і передача атрибутів

Якщо ви використовували slots і передачу атрибутів у Blade-компонентах, почуваєтеся як удома.

Slots дозволяють батькам вставляти вміст у дітей, зберігаючи реактивність:

<livewire:card :$post>
    <h2>{{ $post->title }}</h2>
    <button wire:click="delete({{ $post->id }})">Delete</button>
</livewire:card>

Вміст слота оцінюється в контексті батьківського компонента, тож wire:click="delete" викликає метод батька.

Передача атрибутів дозволяє прокидати HTML-атрибути далі:

<livewire:post.show :$post class="mt-4" />
 
<!-- Inside post.show component -->
<div {{ $attributes }}>
    ...
</div>

# Drag and drop

Сортування перетягуванням без зовнішніх бібліотек:

<ul wire:sort="reorder">
    @foreach ($items as $item)
        <li wire:key="{{ $item->id }}" wire:sort:item="{{ $item->id }}">
            {{ $item->title }}
        </li>
    @endforeach
</ul>
public function reorder($item, $position)
{
    // $item is the ID, $position is the new index
}

Плавні анімації працюють автоматично. Додайте drag handles з wire:sort:handle, забороніть перетягування для інтерактивних елементів через wire:sort:ignore, і перетягуйте між кількома списками з wire:sort:group.

# Плавні переходи

Директива wire:transition додає апаратно-прискорені анімації через View Transitions API:

@if ($showAlertMessage)
    <div wire:transition>
        <!-- Message smoothly fades in/out -->
    </div>
@endif

Для покрокових майстрів або каруселей, де важливий напрям, можна вказати типи переходів:

#[Transition(type: 'forward')]
public function next() { $this->step++; }
 
#[Transition(type: 'backward')]
public function previous() { $this->step--; }

Потім налаштуйте CSS-анімації для кожного напрямку за допомогою псевдоелементів ::view-transition-old() і ::view-transition-new().

# Optimistic UI

Робіть інтерфейс миттєвим. Ці директиви оновлюють сторінку негайно — без очікування відповіді сервера.

wire:show перемикає видимість через CSS (без видалення з DOM і без мережевого запиту):

<div wire:show="showModal">
    <!-- Hidden/shown instantly -->
</div>

wire:text миттєво оновлює текст:

Likes: <span wire:text="likes"></span>

wire:bind реактивно зв'язує будь-який HTML-атрибут:

$dirty відслідковує незбережені зміни:

<div wire:show="$dirty">You have unsaved changes</div>
<div wire:show="$dirty('title')">Title modified</div>

# Стани завантаження

Окрім існуючого wire:loading з v3, Livewire 4 автоматично додає атрибут data-loading до будь-якого елементу, що ініціює мережевий запит.

Це спрощує стилізацію станів завантаження через CSS і дає змогу таргетити сусідні, батьківські або дочірні елементи:

<button wire:click="save" class="data-loading:opacity-50">
    Save <svg class="not-in-data-loading:hidden">...</svg>
</button>

# Вбудовані плейсхолдери

Для lazy-компонентів і islands директива @placeholder дає можливість визначити стан завантаження поряд із вмістом, який вона замінює:

@placeholder
    <div class="animate-pulse h-32 bg-gray-200 rounded"></div>
@endplaceholder
 
<div>
    <!-- Actual content loads here -->
</div>

Ніяких окремих view або методів для плейсхолдерів — ваш скелетон живе в компоненті.

# JavaScript power tools

Коли треба опуститися до JavaScript, Livewire 4 має потрібні інструменти.

wire:ref дає елементам імена для таргетингу:

<livewire:modal wire:ref="modal" />
$this->dispatch('close')->to(ref: 'modal');

До refs також можна звертатися з скриптів компонента:

<input wire:ref="search" type="text" />
 
<script>
    this.$refs.search.addEventListener('keydown', (e) => {
        // Handle keyboard events...
    })
</script>

#[Json] методи повертають дані прямо в JavaScript:

#[Json]
public function search($query)
{
    return Post::where('title', 'like', "%{$query}%")->get();
}
<script>
    let results = await this.search('livewire')
    console.log(results)
</script>

$js дії виконуються лише на стороні клієнта:

<button wire:click="$js.bookmark">Bookmark</button>
 
<script>
    this.$js.bookmark = () => {
        this.bookmarked = !this.bookmarked
        this.save()
    }
</script>

Interceptors дають хук у запити на будь-якому рівні:

<script>
    this.intercept('save', ({ onSuccess, onError }) => {
        onSuccess(() => showToast('Saved!'))
        onError(() => showToast('Failed to save', 'error'))
    })
</script>

Використовуйте глобальні інтерсептори для загальнододаткових сценаріїв, наприклад логіки закінчення сесії:

Livewire.interceptRequest(({ onError }) => {
    onError(({ response, preventDefault }) => {
        if (response.status === 419) {
            preventDefault()
            if (confirm('Session expired. Refresh?')) {
                window.location.reload()
            }
        }
    })
})

# Оновлення

Livewire 4 зберігає високу зворотну сумісність. Ваші існуючі компоненти працюватимуть — новий single-file формат стає стандартом для нових компонентів, але класові компоненти залишаються повністю підтримуваними.

Дивіться посібник з оновлення →

Щоб побачити все в дії, я записав нову серію на Laracasts з детальними прикладами з реального життя. Дивитися серію Livewire 4 →


Livewire 4 вже доступний:

composer require livewire/livewire:^4.0

Для повної документації відвідайте livewire.laravel.com.

Популярні

Logomark Logotype

Інтеграція Laravel Socialite з бібліотекою Google Client PHP

Ви хочете навчитися, як інтегрувати Google OAuth у вашому проекті Laravel, використовуючи Socialite? Дізнайтеся, як налаштувати доступ до сервісів Google, таких як Календар, у нашій сьогоднішній статті

Logomark Logotype

Створення CLI-додатка за допомогою Laravel та Docker

Зазирніть у світ Laravel, де потужний CLI-фреймворк відкриває нові можливості для розробки командного інтерфейсу. Дізнайтеся, як створити просту утиліту для перевірки акцій, яка працює з Docker, та які переваги це може принести у вашому проєкті!

Logomark Logotype

Журнал аудиту в Laravel

Хочете забезпечити повну прозорість у своїх Laravel-додатках? Пакет Laravel Audit Log допоможе вам детально відстежувати всі зміни моделей Eloquent та відповідати вимогам регуляторів. Читайте далі, щоб дізнатися, як цей потужний інструмент може підвищити надійність вашого проєкту