Перейти к содержанию

Компоненты⚓︎

Компоненты Livewire, по сути, представляют собой PHP-классы со свойствами и методами, которые можно вызывать напрямую из шаблона Blade. Эта мощная комбинация позволяет создавать интерактивные full-stack интерфейсы, затрачивая лишь часть усилий и избегая сложности, присущей современным JavaScript-альтернативам.

В этом руководстве рассматривается всё, что вам нужно знать о создании, рендеринге и организации компонентов Livewire. Вы узнаете о различных доступных форматах компонентов (однофайловые, многофайловые и на основе классов), о том, как передавать данные между компонентами и как использовать компоненты в качестве полноценных страниц.

Создание компонентов⚓︎

Вы можете создать компонент, используя Artisan-команду make:livewire:

php artisan make:livewire post.create

Это создаёт однофайловый компонент по пути:

resources/views/components/post/⚡create.blade.php

<?php

use Livewire\Component;

new class extends Component {
    public $title = '';

    public function save()
    {
        // Добавьте свою логику...
    }
};
?>

<div>
    <input wire:model="title" type="text">
    <button wire:click="save">Сохранить</button>
</div>

Зачем эмодзи ⚡?

Возможно, вас интересует, почему в имени файла используется молния. Этот маленький штрих имеет практическое значение: он позволяет мгновенно отличить компоненты Livewire в дереве файлов редактора и в результатах поиска. Поскольку это символ Unicode, он отлично работает на всех платформах — Windows, macOS, Linux, в Git и на продакшен-серверах.

Эмодзи полностью опционален. Если вам это не по душе, вы можете полностью отключить его в файле config/livewire.php:

<?php

'make_command' => [
    'emoji' => false,
],

Предпочитаете соглашения v3?

Если вы предпочитаете классовые компоненты из v3, вы можете восстановить предыдущие настройки по умолчанию с помощью двух строк в config/livewire.php:

<?php

'make_command' => [
    'type' => 'class',
    'emoji' => false,
],

Создание компонентов-страниц⚓︎

При создании компонентов, которые будут использоваться как полноценные страницы, применяйте пространство имён pages::, чтобы организовать их в отдельной директории:

php artisan make:livewire pages::post.create

Это создаёт компонент по пути resources/views/pages/post/⚡create.blade.php. Такое разделение сразу делает очевидным, где у нас страницы-компоненты, а где — обычные переиспользуемые блоки.

Подробнее об использовании компонентов в качестве страниц читайте в разделе Компоненты-страницы ниже. Также вы можете регистрировать собственные пространства имён — смотрите документацию по пространствам имён компонентов.

Многофайловые компоненты⚓︎

По мере роста компонента или проекта однофайловый подход может начать ограничивать. Livewire предлагает альтернативу — многофайловые компоненты, которые разделяют логику, представление, JavaScript и тесты по отдельным файлам для лучшей организации и поддержки в IDE.

Чтобы создать многофайловый компонент, добавьте флаг --mfc:

php artisan make:livewire post.create --mfc

Это создаёт директорию, в которой все связанные файлы находятся вместе:

resources/views/components/post/⚡create/
├── create.php          # PHP-класс
├── create.blade.php    # Blade-шаблон
├── create.js           # JavaScript (опционально)
├── create.css          # Локальные стили (опционально)
├── create.global.css   # Глобальные стили (опционально)
└── create.test.php     # Тест на Pest (опционально, при использовании флага --test)

Опции команды⚓︎

Команда make:livewire принимает следующие опции:

Опция Описание
--sfc Создать однофайловый компонент (по умолчанию)
--mfc Создать многофайловый компонент
--class Создать компонент на основе класса
--type=sfc\|mfc\|class Установить тип компонента явно
--emoji=true\|false Переопределить настройку эмодзи из конфига для этой команды
--test Включить файл теста Pest
--js Включить файл JavaScript (только для многофайловых компонентов)
--css Включить файлы CSS (только для многофайловых компонентов)

Конвертация между форматами⚓︎

Livewire предоставляет команду livewire:convert, которая позволяет легко конвертировать компоненты между однофайловым и многофайловым форматами.

Автоопределение и конвертация:

php artisan livewire:convert post.create
# Однофайловый → Многофайловый (или наоборот)

Явная конвертация в многофайловый формат:

php artisan livewire:convert post.create --mfc

Это распарсит ваш однофайловый компонент, создаст структуру директорий, разделит файлы по соответствующим местам и удалит исходный файл.

Явная конвертация в однофайловый формат:

php artisan livewire:convert post.create --sfc

Это объединяет все файлы обратно в один файл и удаляет директорию.

Файлы тестов удаляются при конвертации в один файл

Если у вашего многофайлового компонента есть файл тестов, вам будет предложено подтвердить конвертацию, так как файлы тестов не могут быть сохранены в однофайловом формате.

Когда использовать каждый формат⚓︎

Однофайловые компоненты (по умолчанию): - Лучше всего подходят для большинства компонентов - Сохраняют связанный код в одном месте - Легко понять с первого взгляда - Идеальны для компонентов малого и среднего размера

Многофайловые компоненты: - Лучше подходят для больших, сложных компонентов - Улучшенная поддержка IDE и навигации - Более четкое разделение, когда компоненты содержат много JavaScript

Компоненты на основе классов: - Знакомы разработчикам по Livewire v2/v3 - Традиционное для Laravel разделение обязанностей - Лучше подходят для команд с устоявшимися соглашениями - См. Компоненты на основе классов ниже

Рендеринг компонентов⚓︎

Вы можете включить компонент Livewire в любой шаблон Blade, используя синтаксис <livewire:component-name />:

<livewire:component-name />

Если компонент находится в поддиректории, вы можете указать это с помощью точки (.):

resources/views/components/post/⚡create.blade.php

<livewire:post.create />

Для компонентов с пространством имён — таких как pages:: — используйте префикс пространства имён:

<livewire:pages::post.create />

Как пути файлов соотносятся с именами компонентов⚓︎

Независимо от используемого формата (однофайловый, многофайловый или на основе классов), имя компонента, которое вы используете в Blade-тегах и маршрутах, всегда одинаково. Префикс с эмодзи ⚡ и структура файла автоматически убираются:

Формат Путь к файлу Имя компонента
Однофайловый resources/views/components/post/⚡create.blade.php post.create
Многофайловый resources/views/components/post/⚡create/create.php post.create
На основе класса app/Livewire/Post/Create.php post.create
Однофайловый (с пространством имён) resources/views/pages/post/⚡create.blade.php pages::post.create
Многофайловый (с пространством имён) resources/views/pages/post/⚡create/create.php pages::post.create

Это означает, что вы можете переключаться между форматами, не изменяя свои Blade-шаблоны или маршруты.

Передача пропсов⚓︎

Чтобы передать данные в компонент Livewire, используйте атрибуты-пропсы прямо в теге компонента:

<livewire:post.create title="Initial Title" />

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

<livewire:post.create :title="$initialTitle" />

Данные, переданные в компонент, принимаются через метод mount():

<?php

use Livewire\Component;

new class extends Component {
    public $title;

    public function mount($title = null)
    {
        $this->title = $title;
    }

    // ...
};

Метод mount() можно рассматривать как конструктор класса. Он выполняется при инициализации компонента, но не запускается при последующих запросах в рамках сессии страницы. Подробнее о методе mount() и других полезных хуках жизненного цикла можно узнать в документации по жизненному циклу.

Чтобы сократить шаблонный код, метод mount() можно вообще не писать — Livewire автоматически присвоит значения всем публичным свойствам, имена которых совпадают с переданными пропсами:

<?php

use Livewire\Component;

new class extends Component {
    public $title; // Автоматическая установка из пропса

    // ...
};

Эти свойства по умолчанию не реактивны

Свойство $title не будет автоматически обновляться, если внешний :title="$initialValue" изменится после начальной загрузки страницы. Это частая причина путаницы при работе с Livewire, особенно у разработчиков, которые привыкли к JavaScript-фреймворкам вроде Vue или React и ожидают, что параметры будут вести себя как «реактивные пропсы». Но не переживайте: Livewire позволяет включить реактивность пропсов по желанию — подробнее о реактивных пропсах.

Передача параметров маршрута как пропсов⚓︎

Когда компонент используется как полноценная страница, вы можете передавать параметры маршрута напрямую в компонент. Параметры маршрута автоматически попадают в метод mount():

Route::livewire('/posts/{id}', 'pages::post.show');
resources/views/pages/post/⚡show.blade.php
<?php

use Livewire\Component;

new class extends Component {
    public $postId;

    public function mount($id)
    {
        $this->postId = $id;
    }
};

Livewire также поддерживает привязку модели маршрута Laravel:

Route::livewire('/posts/{post}', 'pages::post.show');
resources/views/pages/post/⚡show.blade.php
<?php

use App\Models\Post;
use Livewire\Component;

new class extends Component {
    public Post $post; // Автоматически привязывается из маршрута

    // Метод mount() не нужен — Livewire обработает это автоматически
};

Компоненты-страницы⚓︎

Компоненты могут быть напрямую привязаны к маршрутам как полноценные страницы с помощью Route::livewire(). Это одна из самых мощных возможностей Livewire, позволяющая создавать целые страницы без использования традиционных контроллеров.

Route::livewire('/posts/create', 'pages::post.create');

Когда пользователь заходит по адресу /posts/create, Livewire отрендерит компонент pages::post.create внутри файла макета вашего приложения.

Компоненты-страницы работают точно так же, как обычные компоненты, но рендерятся как полноценные страницы и имеют доступ к:

  • Пользовательским макетам
  • Заголовкам страницы
  • Параметрам маршрута и привязке модели
  • Именованным слотам для макета

Полную информацию о компонентах-страницах, включая макет, заголовки и продвинутую маршрутизацию, смотрите в документации по страницам.

Доступ к данным в представлениях⚓︎

Livewire предоставляет несколько способов передачи данных в Blade-представление компонента. Каждый подход имеет свои особенности по производительности и безопасности.

Свойства компонента⚓︎

Самый простой способ — использовать публичные свойства, которые автоматически становятся доступны в Blade-шаблоне:

<?php

use Livewire\Component;

new class extends Component {
    public $title = 'Мой пост';
};
<div>
    <h1>{{ $title }}</h1>
</div>

Защищённые свойства должны быть доступны через $this->:

<?php

public $title = 'Мой пост';           // Доступно как {{ $title }}
protected $apiKey = 'secret-key';    // Доступно как {{ $this->apiKey }}

Защищённые свойства не отправляются на клиент

В отличие от публичных свойств, защищённые свойства никогда не отправляются на фронтенд и не могут быть изменены пользователями. Это делает их безопасными для конфиденциальных данных. Однако они не сохраняются между запросами, что ограничивает их полезность в большинстве сценариев Livewire. Лучше всего использовать их для статических значений, заданных прямо в объявлении свойства, которые вы не хотите раскрывать на стороне клиента.

Полную информацию о свойствах, включая поведение сохранения и продвинутые возможности, смотрите в документации по свойствам.

Вычисляемые свойства⚓︎

Вычисляемые свойства — это методы, которые ведут себя как кэшированные свойства. Они идеально подходят для дорогостоящих операций, таких как запросы к базе данных:

<?php

use Livewire\Attributes\Computed;

#[Computed]
public function posts()
{
    return Post::with('author')->latest()->get();
}
<div>
    @foreach ($this->posts as $post)
        <article wire:key="{{ $post->id }}">{{ $post->title }}</article>
    @endforeach
</div>

Обратите внимание на префикс $this-> — он указывает Livewire, что нужно вызвать метод и закэшировать результат только для текущего запроса (не между запросами). Подробнее смотрите в разделе вычисляемые свойства.

Передача данных из метода render()⚓︎

Аналогично контроллеру, вы можете передавать данные прямо в представление через метод render():

<?php

public function render()
{
    return $this->view([
        'author' => Auth::user(),
        'currentTime' => now(),
    ]);
}

Имейте в виду, что render() выполняется при каждом обновлении компонента, поэтому избегайте здесь дорогостоящих операций, если только вам не нужны свежие данные при каждом обновлении.

Организация компонентов⚓︎

Хотя Livewire автоматически обнаруживает компоненты в стандартной директории resources/views/components/, вы можете настроить, где именно Livewire будет искать компоненты, и организовать их с помощью пространств имён.

Пространства имён компонентов⚓︎

Пространства имён компонентов позволяют организовать компоненты в отдельных директориях с удобным синтаксисом обращения.

По умолчанию Livewire предоставляет два пространства имён:

  • pages:: — указывает на resources/views/pages/
  • layouts:: — указывает на resources/views/layouts/

Вы можете определить дополнительные пространства имён в файле config/livewire.php:

<?php

'component_namespaces' => [
    'layouts' => resource_path('views/layouts'),
    'pages' => resource_path('views/pages'),
    'admin' => resource_path('views/admin'),    // Пользовательское пространство имён
    'widgets' => resource_path('views/widgets'), // Ещё одно пользовательское пространство имён
],

Затем используйте их при создании, рендеринге и маршрутизации:

php artisan make:livewire admin::users-table
<livewire:admin::users-table />
Route::livewire('/admin/users', 'admin::users-table');

Дополнительные места для компонентов⚓︎

Если вы хотите, чтобы Livewire обнаруживал компоненты в дополнительных директориях помимо стандартных, вы можете настроить их в файле config/livewire.php:

<?php

'component_locations' => [
    resource_path('views/components'),
    resource_path('views/admin/components'),
    resource_path('views/widgets'),
],

Теперь Livewire будет автоматически обнаруживать компоненты во всех этих директориях.

Программная регистрация⚓︎

Для более динамичных сценариев (например, при разработке пакетов или конфигурации во время выполнения) вы можете регистрировать компоненты, местоположения и пространства имён программно в сервис-провайдере:

Регистрация отдельного компонента:

<?php

use Livewire\Livewire;

// В методе boot() сервис-провайдера (например, App\Providers\AppServiceProvider)
Livewire::addComponent(
    name: 'custom-button',
    viewPath: resource_path('views/ui/button.blade.php')
);

Регистрация директории компонентов:

<?php

Livewire::addLocation(
    viewPath: resource_path('views/admin/components')
);

Регистрация пространства имён:

<?php

Livewire::addNamespace(
    namespace: 'ui',
    viewPath: resource_path('views/ui')
);

Этот подход полезен, когда вам нужно регистрировать компоненты условно или когда вы создаёте Laravel-пакеты, предоставляющие компоненты Livewire.

Регистрация классовых компонентов⚓︎

Для классовых компонентов используйте те же методы, но с параметром class вместо path:

<?php

use Livewire\Livewire;

// В методе boot() сервис-провайдера (например, App\Providers\AppServiceProvider)

// Регистрация отдельного классового компонента
Livewire::addComponent(
    name: 'todos',
    class: \App\Livewire\Todos::class
);

// Регистрация места для классовых компонентов
Livewire::addLocation(
    classNamespace: 'App\\Admin\\Livewire'
);

// Создание пространства имён для классовых компонентов
Livewire::addNamespace(
    namespace: 'admin',
    classNamespace: 'App\\Admin\\Livewire',
    classPath: app_path('Admin/Livewire'),
    classViewPath: resource_path('views/admin/livewire')
);

Классовые компоненты⚓︎

Для команд, мигрирующих с Livewire v3, или для тех, кто предпочитает более традиционную структуру Laravel, Livewire полностью поддерживает классовые компоненты. При этом подходе PHP-класс и Blade-представление разделены на разные файлы в их стандартных местах.

Создание классовых компонентов⚓︎

php artisan make:livewire CreatePost --class

Это создаёт два отдельных файла:

app/Livewire/CreatePost.php

<?php

namespace App\Livewire;

use Livewire\Component;

class CreatePost extends Component
{
    public function render()
    {
        return view('livewire.create-post');
    }
}

resources/views/livewire/create-post.blade.php

<div>
    { ... }
</div>

Когда использовать классовые компоненты⚓︎

Используйте классовые компоненты, когда:

  • Вы мигрируете с Livewire v2/v3
  • Ваша команда предпочитает более традиционную структуру файлов
  • У вас уже сложились устоявшиеся соглашения вокруг классовой архитектуры

Используйте однофайловые или многофайловые компоненты, когда:

  • Вы начинаете новый проект на Livewire v4
  • Вы хотите лучшую колокацию компонентов
  • Вы хотите следовать самым последним соглашениям Livewire

Настройка типа компонентов по умолчанию⚓︎

Если вы хотите, чтобы по умолчанию создавались классовые компоненты, настройте это в файле config/livewire.php:

<?php

'make_command' => [
    'type' => 'class',
],

Настройка заготовок компонентов⚓︎

Вы можете настроить файлы (или заготовки), которые Livewire использует для генерации новых компонентов, выполнив:

php artisan livewire:stubs

Это создаёт файлы-заготовки в вашем приложении, которые вы можете изменить:

Заготовки однофайловых компонентов:

  • stubs/livewire-sfc.stub — Однофайловые компоненты

Заготовки многофайловых компонентов:

  • stubs/livewire-mfc-class.stub — PHP-класс для многофайловых компонентов
  • stubs/livewire-mfc-view.stub — Blade-представление для многофайловых компонентов
  • stubs/livewire-mfc-js.stub — JavaScript для многофайловых компонентов
  • stubs/livewire-mfc-test.stub — Тест на Pest для многофайловых компонентов

Заготовки классовых компонентов:

  • stubs/livewire.stub — PHP-класс для классовых компонентов
  • stubs/livewire.view.stub — Blade-представление для классовых компонентов

Дополнительные заготовки:

  • stubs/livewire.attribute.stub — Классы атрибутов
  • stubs/livewire.form.stub — Классы форм

После публикации Livewire будет автоматически использовать ваши кастомные заготовки при создании новых компонентов.

Устранение неисправностей⚓︎

Компонент не найден⚓︎

Симптом: Сообщение об ошибке вида "Component [post.create] not found" или "Unable to find component"

Решения:

  • Убедитесь, что файл компонента существует по ожидаемому пути
  • Проверьте, что имя компонента в вашем представлении соответствует структуре файлов (точки для поддиректорий)
  • Для компонентов с пространством имён убедитесь, что пространство имён определено в config/livewire.php или зарегистрировано вручную в сервис-провайдере
  • Попробуйте очистить кэш представлений: php artisan view:clear

Компонент отображается пустым или не рендерится⚓︎

Распространённые причины:

  • Отсутствует корневой элемент в Blade-шаблоне (Livewire требует ровно один корневой элемент)
  • Синтаксические ошибки в PHP-части компонента
  • Проверьте логи Laravel на наличие подробных сообщений об ошибках

Конфликты имён классов⚓︎

Симптом: Ошибки о дублирующихся именах классов при использовании однофайловых компонентов

Решение: Это может происходить, если у вас несколько однофайловых компонентов с одинаковым именем в разных директориях. Варианты:

  • Переименуйте один из компонентов, чтобы имя было уникальным
  • Добавьте пространство имён одной из директорий для более чёткого разделения

Смотрите также⚓︎

  • Свойства — Управление состоянием и данными компонента
  • Действия — Обработка взаимодействий пользователя с помощью методов
  • Страницы — Использование компонентов как полноценных страниц с маршрутизацией
  • Вложенные компоненты — Композиция компонентов и передача данных между ними
  • Хуки жизненного цикла — Выполнение кода в определённых точках жизненного цикла компонента