Blade-компоненты: переиспользуемый UI

Blade-компоненты — современный способ собирать интерфейс из переиспользуемых кирпичиков с входными параметрами (props) и контентом (slots).

Суть: компонент — это самостоятельный элемент UI (кнопка, карточка, алерт), который вызывается как HTML-тег <x-alert />, принимает props для настройки и slot для содержимого.

Наследование шаблонов хорошо для каркаса страницы, но для мелких повторяющихся элементов — кнопок, карточек, уведомлений — нужен инструмент гибче. Это Blade-компоненты. Они работают как собственные HTML-теги: вы описываете компонент один раз, а потом вставляете его где угодно одной строкой, настраивая через атрибуты.

Есть два вида компонентов. Анонимные — это просто шаблон в папке resources/views/components, без PHP-класса; идеальны для простого UI. Классовые имеют PHP-класс с логикой; нужны, когда внутри есть вычисления. Начинать стоит с анонимных — их проще всего понять.

Анонимный компонент

Создадим компонент-уведомление. Файл resources/views/components/alert.blade.php:

{{-- объявляем входные параметры со значениями по умолчанию --}}
@props(['type' => 'info'])

<div {{ $attributes->merge(['class' => 'alert alert-'.$type]) }}>
    {{ $slot }}   {{-- сюда попадёт содержимое компонента --}}
</div>

Теперь используем его как тег. Имя начинается с x-, props передаются как атрибуты, а содержимое между тегами попадёт в $slot:

<x-alert type="danger" class="mb-4">
    Ошибка: товар не найден!
</x-alert>

<x-alert>
    Обычное информационное сообщение.
</x-alert>

Как работает под капотом

Директива @props объявляет ожидаемые параметры и их значения по умолчанию. Переменная $slot хранит всё, что вы написали между открывающим и закрывающим тегом. А $attributes собирает все «лишние» HTML-атрибуты, не объявленные в props (например, class="mb-4"), и метод merge() аккуратно объединяет их с собственными классами компонента, не затирая ни те, ни другие.

  Вызов:  <x-alert type="danger" class="mb-4">Текст</x-alert>

          type="danger"  -> prop  $type = 'danger'
          class="mb-4"   -> $attributes (не объявлен в props)
          Текст          -> $slot

  merge:  'alert alert-danger' + 'mb-4'
          = class="alert alert-danger mb-4"

Смоделируем логику компонента на Python: props со значениями по умолчанию, слияние атрибутов и подстановка слота.

Попробуй сам ▶

# Логика Blade-компонента: props + merge атрибутов + slot
def alert(slot, type='info', extra_class=''):
    base = f'alert alert-{type}'                 # собственные классы
    merged = (base + ' ' + extra_class).strip()  # $attributes->merge()
    return f'<div class="{merged}">{slot}</div>'

print(alert('Ошибка!', type='danger', extra_class='mb-4'))
print(alert('Просто информация'))   # type по умолчанию = info

Частые ошибки

  • Затирать классы вместо merge. Если присвоить class напрямую, переданный класс потеряется. Используйте $attributes->merge().
  • Забыть @props. Без объявления параметр окажется в $attributes и просочится в HTML как атрибут.
  • Не чистить кэш. После изменений иногда нужно php artisan view:clear, чтобы увидеть результат.

Best practices

  • Держите компоненты маленькими и сфокусированными на одной задаче.
  • Для простого UI используйте анонимные компоненты, классовые — только при наличии логики.
  • Всегда применяйте $attributes->merge(), чтобы внешние классы и атрибуты не терялись.

Стоит чётко понимать разницу между анонимными и классовыми компонентами на практике. Анонимный компонент — это один файл-шаблон без сопровождающего PHP-класса; он идеален, когда вся логика сводится к подстановке props и вёрстке. Как только внутри появляется нетривиальная подготовка данных (например, вычисление вариантов кнопки по статусу заказа или формирование сложного набора классов), переходят к классовому компоненту: его создают командой php artisan make:component Alert, и тогда рядом с шаблоном появляется класс с публичными свойствами и методами, доступными в разметке. Ещё одна важная деталь — именованные слоты. Кроме основного $slot компонент может принимать несколько именованных областей: например, у карточки бывают слоты заголовка и подвала. Их объявляют тегами <x-slot:header> и выводят внутри компонента как переменную. Это позволяет строить богатые, но при этом аккуратные переиспользуемые блоки интерфейса, не превращая компонент в свалку условий.

Итог: Blade-компоненты превращают интерфейс в набор переиспользуемых тегов с props и slots — это современный, чистый способ строить UI. Дальше переходим к работе с базой данных: миграциям и Eloquent.

Проверьте себя
1. Что хранит переменная $slot в Blade-компоненте?
AИмя компонента
BСодержимое между открывающим и закрывающим тегом компонента
CСписок маршрутов
DСтили CSS
2. Зачем нужен $attributes->merge() в компоненте?
AЧтобы удалить все атрибуты
BЧтобы объединить переданные извне атрибуты с собственными, не затирая их
CЧтобы создать маршрут
DЧтобы подключить базу данных