Layout Blade + Componente-bueno componente in
Layout Blade + Componente
Vamos a crear un ejemplo completo con:
Un layout en Blade (el cascarón de la página).
Un componente chiquito que se usa dentro del layout.
Archivo 1: El layout
resources/views/layouts/app.blade.php
<!DOCTYPE html>
<html>
<head>
<title>@yield('title', 'Mi App')</title>
</head>
<body>
<header>Mi sitio web</header>
<main>
@yield('content')
</main>
<footer>© 2026</footer>
</body>
</html>Este es un layout clásico de Blade. Usa @yield, no $slot. No es un componente. Es una plantilla normal que otras vistas van a extender.
@yield('title')→ hueco para el título.@yield('content')→ hueco para el contenido.
Archivo 2: El componente
resources/views/components/alerta.blade.php
@props(['tipo' => 'info'])
<div class="alerta alerta-{{ $tipo }}">
{{ $slot }}
</div>Este sí es un componente. Tiene:
@props→ recibetipo.$slot→ recibe el texto.
Archivo 3: La vista que usa el layout y el componente
resources/views/home.blade.php
@extends('layouts.app')
@section('title', 'Lista de tareas')
@section('content')
<h1>¡Bienvenido!</h1>
<x-alerta tipo="exito">
Todo salió bien
</x-alerta>
<ul>
<li>Tarea 1</li>
<li>Tarea 2</li>
</ul>
@endsectionAquí pasa algo importante:
@extends('layouts.app')→ usa el layout clásico.@section('title', ...)→ llena el@yield('title')del layout.@section('content') ... @endsection→ llena el@yield('content')del layout.Dentro de
@section('content'), se usa<x-alerta>→ ahí entra el componente.
¿Qué pasa paso a paso?
Paso 1: Laravel abre home.blade.php y ve @extends('layouts.app'). Entonces carga layouts/app.blade.php.
Paso 2: Laravel busca @yield('title') y lo reemplaza con "Lista de tareas".
Paso 3: Laravel busca @yield('content') y lo reemplaza con todo el contenido del @section('content').
Paso 4: Pero antes de meterlo, procesa el <x-alerta> que hay adentro.
Abre alerta.blade.php:
$tipo="exito"$slot="Todo salió bien"
Produce:
<div class="alerta alerta-exito">
Todo salió bien
</div>Paso 5: Ese HTML reemplaza al <x-alerta> dentro del contenido.
Paso 6: El contenido final del @yield('content') queda así:
<h1>¡Bienvenido!</h1>
<div class="alerta alerta-exito">
Todo salió bien
</div>
<ul>
<li>Tarea 1</li>
<li>Tarea 2</li>
</ul>Paso 7: Laravel lo mete en el layout, dentro de <main>.
HTML final
<!DOCTYPE html>
<html>
<head>
<title>Lista de tareas</title>
</head>
<body>
<header>Mi sitio web</header>
<main>
<h1>¡Bienvenido!</h1>
<div class="alerta alerta-exito">
Todo salió bien
</div>
<ul>
<li>Tarea 1</li>
<li>Tarea 2</li>
</ul>
</main>
<footer>© 2026</footer>
</body>
</html>La clave: dos mecanismos distintos trabajando juntos
| Mecanismo | Archivo | Cómo funciona |
|---|---|---|
| Layout clásico | layouts/app.blade.php | Usa @yield para los huecos |
| Componente | components/alerta.blade.php | Usa $slot para el contenido |
Son dos cosas diferentes:
@yield→ hueco de un layout clásico (se llena con@section).$slot→ hueco de un componente (se llena con lo que va entre<x-alerta>y</x-alerta>).
En este ejemplo, ambos conviven:
El layout usa
@yield.El componente usa
$slot.La vista
home.blade.phpllena el@yieldcon@section, y dentro de ese@sectionusa<x-alerta>para llenar el$slot.
Diferencia con el ejemplo anterior
En el ejemplo anterior que viste, el layout era un componente (<x-layout>) y usaba $slot.
Aquí el layout es clásico (@extends + @yield) y el componente (<x-alerta>) usa $slot.
Ambos enfoques son válidos:
| Enfoque | Layout | Contenido |
|---|---|---|
| Componentes | <x-layout> con $slot | <x-alerta> con $slot |
| Clásico + componentes | @extends + @yield | <x-alerta> con $slot |
Puedes mezclarlos. No hay problema.
Resumen
Layout clásico →
layouts/app.blade.phpcon@yield.Vista que lo usa →
home.blade.phpcon@extendsy@section.Componente →
components/alerta.blade.phpcon@propsy$slot.Uso del componente →
<x-alerta>...</x-alerta>dentro del@section.$slot→ recibe el contenido que va entre<x-alerta>y</x-alerta>.@yield→ recibe el contenido de los@sectionde la vista.
Cada uno tiene su hueco, y Laravel los une en el HTML final.
Cómo funciona el $slot y cómo meter datos a un componente
1. Qué es el $slot
El $slot es una variable especial que Laravel pone a tu disposición dentro de cualquier componente Blade. Contiene todo el contenido HTML/texto que escribiste entre las etiquetas de apertura y cierre del componente.
<x-alerta tipo="exito">
Todo salió bien <-- ESTO es el $slot
</x-alerta>Dentro de alerta.blade.php, {{ $slot }} se reemplaza por "Todo salió bien".
Regla mental: $slot = el "relleno" que va dentro del componente. Es el equivalente a un @yield('content') pero para componentes.
2. Cómo meter datos al componente: dos vías
Hay dos formas distintas de pasar información a un componente, y conviene no confundirlas:
| Vía | Cómo se escribe | Cómo se lee dentro | Para qué sirve |
|---|---|---|---|
| Atributos | <x-alerta tipo="exito"> | @props(['tipo' => 'info']) → $tipo | Datos de configuración (tipo, color, id, etc.) |
| Slot | Contenido entre etiquetas | {{ $slot }} | Contenido principal (texto, HTML, otros componentes) |
En el ejemplo:
<x-alerta tipo="exito">
Todo salió bien
</x-alerta>tipo="exito"→ llega como atributo/prop → se usa enalerta-{{ $tipo }}Todo salió bien→ llega como slot → se pinta con{{ $slot }}
3. @props: declarar qué atributos acepta el componente
@props(['tipo' => 'info'])Esto hace tres cosas:
Declara que el componente acepta un atributo llamado
tipo.Define un valor por defecto (
'info') si no se lo pasan.Extrae ese atributo de la bolsa de atributos, para que no se imprima como atributo HTML suelto.
Si no declaras @props, cualquier atributo que pases se renderiza tal cual en el HTML (comportamiento de "attribute bag"), lo cual puede no ser lo que quieres.
4. Variantes útiles
a) Valor por defecto si no se pasa el prop
@props(['tipo' => 'info'])<x-alerta>...</x-alerta>→$tipo = 'info'<x-alerta tipo="exito">...</x-alerta>→$tipo = 'exito'
b) Slots con nombre (varios huecos)
Si quieres más de un hueco, además del principal:
<!-- components/card.blade.php -->
@props(['titulo'])
<div class="card">
<h2>{{ $titulo }}</h2>
<div>{{ $slot }}</div>
<footer>{{ $footer }}</footer>
</div>Uso:
<x-card titulo="Mi tarjeta">
Contenido principal (va al $slot)
<x-slot:footer>
Pie de la tarjeta
</x-slot:footer>
</x-card>Aquí:
titulo→ propcontenido entre
<x-card>y<x-slot:footer>→$slotcontenido dentro de
<x-slot:footer>→$footer
c) Atributos extra ($attributes)
Todo lo que no declares en @props cae en $attributes, que puedes volcar en el HTML:
@props(['tipo' => 'info'])
<div {{ $attributes->merge(['class' => "alerta alerta-$tipo"]) }}>
{{ $slot }}
</div>Uso:
<x-alerta tipo="exito" id="msg-1" class="mt-4">
Todo salió bien
</x-alerta>Resultado:
<div id="msg-1" class="alerta alerta-exito mt-4">
Todo salió bien
</div>5. Resumen visual del flujo
<x-alerta tipo="exito"> <-- atributo --> $tipo (vía @props)
Todo salió bien <-- contenido --> $slot (vía {{ $slot }})
</x-alerta>Dentro del componente:
@props(['tipo' => 'info']) {{-- recibe atributos --}}
<div class="alerta alerta-{{ $tipo }}">
{{ $slot }} {{-- recibe el contenido --}}
</div>6. La clave para no confundirte
$slot= "lo que va dentro de las etiquetas del componente". Es contenido.@props/$tipo= "lo que va en los atributos de la etiqueta del componente". Es configuración.
Son dos canales distintos y complementarios: uno para qué se muestra (slot) y otro para cómo se muestra (props).
Comentarios
Publicar un comentario