Componentes Blade desde cero-super

Componentes Blade desde cero

Voy a explicarte los componentes Blade desde lo más básico, partiendo de las vistas normales, pasando por los layouts, y llegando a los componentes. Al final entenderás cómo se llama el componente, cómo se usa, y cómo se le meten datos.


Parte 1: La vista Blade normal (el punto de partida)

Una vista Blade es solo un archivo .blade.php con HTML y un poco de sintaxis especial.

resources/views/saludo.blade.php

blade
<!DOCTYPE html>
<html>
    <head>
        <title>Saludo</title>
    </head>
    <body>
        <h1>Hola, {{ $nombre }}</h1>
        <p>Bienvenido a mi sitio</p>
    </body>
</html>

Aquí:

  • {{ $nombre }} → variable que le pasa el controlador.

  • La vista es autónoma: tiene su propio <html>, <head>, <body>.

Problema: si tienes 20 vistas, repites el <html>, <head>, <body> en cada una. Ahí entran los layouts.


Parte 2: El layout clásico (evitar repetir el cascarón)

Un layout es una plantilla con huecos (@yield) que otras vistas rellenan.

resources/views/layouts/app.blade.php

blade
<!DOCTYPE html>
<html>
    <head>
        <title>@yield('title', 'Mi App')</title>
    </head>
    <body>
        <header>Mi sitio web</header>

        <main>
            @yield('content')     {{-- hueco principal --}}
        </main>

        <footer>© 2026</footer>
    </body>
</html>

Cómo se usa desde una vista:

resources/views/home.blade.php

blade
@extends('layouts.app')

@section('title', 'Lista de tareas')

@section('content')
    <h1>¡Bienvenido!</h1>
    <ul>
        <li>Tarea 1</li>
        <li>Tarea 2</li>
    </ul>
@endsection

Cómo funciona:

  • @extends → "usa este layout como cascarón".

  • @section('title', ...) → rellena el @yield('title').

  • @section('content') ... @endsection → rellena el @yield('content').

Idea clave: el layout tiene huecos (@yield) y la vista los llena (@section).


Parte 3: El componente (una pieza reutilizable con su propio hueco)

Un componente es como un layout mini, pero reutilizable en cualquier parte, no solo como cascarón de página.

3.1 ¿Cómo se llama el componente?

Aquí viene lo importante. El nombre del componente se deriva de la ruta del archivo. No hay que registrar nada manualmente en Laravel moderno.

ArchivoNombre al usarlo
resources/views/components/alerta.blade.php<x-alerta>
resources/views/components/boton.blade.php<x-boton>
resources/views/components/card.blade.php<x-card>
resources/views/components/forms/input.blade.php<x-forms.input>
resources/views/components/ui/boton-primario.blade.php<x-ui.boton-primario>

Reglas del nombre:

  • Todo lo que está dentro de components/ se convierte en un componente.

  • La carpeta se convierte en prefijo separado por punto: forms/input → x-forms.input.

  • Los guiones se mantienen: boton-primario → x-ui.boton-primario.

  • El prefijo x- es obligatorio en el uso.

Así que el nombre del componente = ruta del archivo desde components/, con / → . y prefijo x-.

3.2 ¿Cómo se ve por dentro?

resources/views/components/alerta.blade.php

blade
@props(['tipo' => 'info'])

<div class="alerta alerta-{{ $tipo }}">
    {{ $slot }}
</div>

Tres piezas:

  1. @props([...]) → declara qué atributos acepta el componente y sus valores por defecto.

  2. $tipo → variable que viene de los atributos (tipo="exito").

  3. $slot → todo el contenido que va entre las etiquetas del componente.

3.3 ¿Cómo se usa?

resources/views/home.blade.php

blade
@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>
@endsection

Aquí:

  • <x-alerta tipo="exito"> → usa el componente alerta.

  • tipo="exito" → atributo que llega a $tipo.

  • Todo salió bien → contenido que llega a $slot.

3.4 ¿Cómo se meten datos? Dos canales distintos

CanalCómo se escribeCómo se lee dentroPara qué
Atributos<x-alerta tipo="exito">@props(['tipo' => 'info']) → $tipoConfiguración (tipo, color, id…)
SlotContenido entre etiquetas{{ $slot }}Contenido principal (texto, HTML…)

Regla mental:

  • $slot = "lo que va dentro de las etiquetas". Es contenido.

  • @props / $tipo = "lo que va en los atributos". Es configuración.


Parte 4: Ejemplo completo paso a paso (lo que pasa cuando Laravel renderiza)

Toma esto:

blade
<x-alerta tipo="exito">
    Todo salió bien
</x-alerta>

Paso 1: Laravel ve <x-alerta> y busca resources/views/components/alerta.blade.php.

Paso 2: Procesa @props(['tipo' => 'info']):

  • Como le pasaste tipo="exito", $tipo = "exito".

  • Si no hubieras pasado tipo, sería $tipo = "info".

Paso 3: Procesa {{ $slot }}:

  • $slot = "Todo salió bien".

Paso 4: Renderiza:

html
<div class="alerta alerta-exito">
    Todo salió bien
</div>

Paso 5: Ese HTML reemplaza al <x-alerta> dentro del @section('content') de home.blade.php.

Paso 6: El @section('content') llena el @yield('content') del layout.

Paso 7: HTML final:

html
<!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>

Parte 5: Los tres mecanismos comparados

MecanismoArchivoHuecoCómo se llena
Vista normalsaludo.blade.php{{ $variable }}Controlador pasa variables
Layout clásicolayouts/app.blade.php@yield('content')@section('content')
Componentecomponents/alerta.blade.php{{ $slot }} + $propsContenido entre etiquetas + atributos

Conviven sin problema. En el ejemplo final:

  • El layout usa @yield.

  • El componente usa $slot.

  • La vista home.blade.php llena el @yield con @section, y dentro de ese @section usa <x-alerta> para llenar el $slot.


Parte 6: Cómo se llama el componente — resumen definitivo

El nombre del componente se forma así:

text
resources/views/components/alerta.blade.php
        ↓
   <x-alerta>          (en cualquier vista)

resources/views/components/ui/boton.blade.php
        ↓
   <x-ui.boton>

resources/views/components/forms/input.blade.php
        ↓
   <x-forms.input>

Fórmula:

  1. Quita resources/views/components/ y .blade.php.

  2. Cambia / por ..

  3. Añade el prefijo x-.

No hay que registrar nada. Laravel lo descubre automáticamente (componentes anónimos).


Parte 7: Tres formas de pasar datos al componente

a) Atributo simple → $props

blade
<x-alerta tipo="exito">...</x-alerta>
blade
@props(['tipo' => 'info'])
<div class="alerta-{{ $tipo }}">{{ $slot }}</div>

b) Contenido → $slot

blade
<x-alerta>Todo salió bien</x-alerta>
blade
{{ $slot }}   {{-- Todo salió bien --}}

c) Slots con nombre (varios huecos)

blade
<x-card titulo="Mi tarjeta">
    Contenido principal
    <x-slot:footer>
        Pie de la tarjeta
    </x-slot:footer>
</x-card>
blade
@props(['titulo'])
<div class="card">
    <h2>{{ $titulo }}</h2>
    <div>{{ $slot }}</div>
    <footer>{{ $footer }}</footer>
</div>

Parte 8: Chuleta final

blade
{{-- 1. Definir el componente: resources/views/components/alerta.blade.php --}}
@props(['tipo' => 'info'])          {{-- atributos con default --}}

<div class="alerta alerta-{{ $tipo }}">
    {{ $slot }}                     {{-- contenido entre etiquetas --}}
</div>

{{-- 2. Usarlo en cualquier vista --}}
<x-alerta tipo="exito">
    Todo salió bien
</x-alerta>

{{-- 3. Resultado --}}
<div class="alerta alerta-exito">
    Todo salió bien
</div>

Lo esencial:

  • Nombre del componente = ruta del archivo desde components/ con / → . y prefijo x-.

  • @props = atributos (configuración).

  • $slot = contenido (lo que va entre las etiquetas).

  • @yield = hueco de layout clásico (se llena con @section).

  • $slot = hueco de componente (se llena con el contenido entre etiquetas).

  • Son dos mecanismos distintos que pueden convivir en la misma vista

Comentarios

Entradas más populares de este blog

02 -Rutas en Laravel

01-04-convencion nombres

1-4-Evolución en PHP Puro-Credenciales en Body/Query String: