Un componente Blazor es una parte autocontenida de la interfaz que combina marcado y lógica de presentación.
Una página completa como Home, un formulario o un botón pueden ser componentes. Esta composición permite dividir la interfaz en piezas reutilizables que encajan entre sí.
Un componente en Blazor es una pieza de interfaz de usuario (UI) autocontenida que encapsula:
- Renderizado: Su apariencia (HTML + CSS).
- Lógica: Su comportamiento (C#).
Hoy vamos a aprender a crearlos, organizarlos y, lo más importante para mantener la cordura en proyectos grandes: cómo separar el código de la vista.
Estructura básica de un componente
Técnicamente, un componente es un archivo con extensión .razor.
El nombre del archivo es importante: debe comenzar con mayúscula y seguir PascalCase. Por ejemplo: MiTarjeta.razor.
¿Por qué mayúscula? Porque Blazor compila cada archivo .razor en una Clase C#. Por convención de .NET, las clases usan PascalCase. Además, ayuda a distinguir las etiquetas HTML (<div>) de nuestros componentes (<MiTarjeta>).
Vamos a crear un componente simple para mostrar información de un usuario. Lo llamaremos UserProfile.razor.
<div class="card" style="width: 18rem;">
<div class="card-body">
<h5 class="card-title">@UserName</h5>
<p class="card-text">Rol: @Role</p>
<button class="btn btn-primary" @onclick="ChangeRole">Ascender</button>
</div>
</div>
@code {
// Estado del componente
private string UserName = "Luis Llamas";
private string Role = "Editor";
// Comportamiento
private void ChangeRole()
{
Role = "Administrador";
}
}Esta es la estructura de archivo único. El HTML queda arriba y el bloque @code, con la lógica C#, debajo. Es una opción directa para componentes pequeños.
Cómo anidar componentes
Lo interesante aparece cuando empezamos a usar componentes dentro de otros. Para usar nuestro UserProfile dentro de, por ejemplo, Home.razor, simplemente lo invocamos como si fuera una etiqueta HTML.
@page "/"
<PageTitle>Inicio</PageTitle>
<h1>Panel de Control</h1>
<div class="d-flex gap-3">
<UserProfile />
<UserProfile />
<UserProfile />
</div>Al compilar, Blazor sustituye cada etiqueta <UserProfile /> por una instancia de la clase UserProfile y renderiza su contenido. Cada instancia mantiene su propio estado independiente. Si haces clic en “Ascender” en el primer usuario, los otros dos no se ven afectados.
Espacios de nombres y _Imports.razor
A veces, al intentar usar un componente, el editor no lo reconoce (no se pone de color verde/violeta). Esto suele ser porque el componente está en una carpeta diferente y no hemos importado el namespace.
Si UserProfile.razor está en la carpeta Components/UI, su namespace completo es MiProyecto.Components.UI.
Para no repetir @using MiProyecto.Components.UI en cada archivo, puedes añadirlo a _Imports.razor. Sus directivas se aplican a los componentes de la misma carpeta y de sus subcarpetas; si está en la raíz adecuada, cubrirá toda la aplicación.
Separación de código con code-behind
El enfoque de archivo único (@code) está muy bien para demos y componentes visuales simples. Pero, ¿qué pasa cuando tenemos un componente complejo con 200 líneas de lógica, inyección de dependencias y llamadas a base de datos?
Que el archivo .razor se vuelve inmanejable.
Para evitarlo, podemos usar code-behind, que separa físicamente la vista (.razor) de la lógica (.cs). El enfoque resultará familiar si vienes de WPF o Web Forms.
Cómo implementar code-behind
La clave es el uso de Clases Parciales (partial).
Blazor compila el archivo .razor en una clase C#. Si creamos otra clase partial con el mismo nombre y espacio de nombres, el compilador fusiona ambas partes.
Paso 1: El archivo de vista (UserProfile.razor)
Eliminamos el bloque @code (o dejamos solo lo mínimo indispensable puramente visual).
<div class="card">
<h3>@UserName</h3>
<button @onclick="UpdateUser">Actualizar</button>
</div>Paso 2: El archivo de lógica (UserProfile.razor.cs)
Creamos una clase C# convencional. Por convención, la llamamos igual que el componente añadiendo .cs.
En Visual Studio, si nombras el archivo UserProfile.razor.cs, lo anidará automáticamente debajo del archivo .razor en el explorador de soluciones, manteniendo todo ordenado.
// UserProfile.razor.cs
using Microsoft.AspNetCore.Components;
namespace MiProyecto.Components.Pages
{
// IMPORTANTE: Debe ser public y partial
public partial class UserProfile
{
// Las dos partes forman la misma clase, así que puede ser private
private string UserName { get; set; } = "Luis";
private void UpdateUser()
{
UserName = "Usuario Actualizado";
}
}
}¿Qué enfoque debemos usar?
Nos gusta el código limpio, pero también somos pragmáticos. No hay una única receta, pero esta es nuestra recomendación:
| Enfoque | Cuándo usarlo | Ventajas |
|---|---|---|
Bloque @code | Componentes pequeños y principalmente visuales (botones, insignias o tarjetas simples). | • Menos archivos que gestionar. • Contexto visual inmediato. • Desarrollo rápido. |
| Code-behind | Páginas (@page), formularios complejos o bastante lógica de presentación. | • Archivos más pequeños y legibles. • Separación de responsabilidades. • Mejor control de versiones (Git) al separar cambios de diseño y lógica. |