Esta documentación está en fase de desarrollo y puede contener errores.

Carga y rendimiento

Carga y contenido diferido: distingue procesar una accion, pintar la UI por primera vez, aplazar bloques pesados y contener errores de render.

Cuatro situaciones que se confunden, cuatro componentes. Hay una accion en marcha y quieres avisar de que algo se esta procesando: DnzLoader. La interfaz todavia no esta lista y quieres mostrar el hueco que va a ocupar: DnzSkeleton. Tienes una subpagina o seccion cara de pintar y quieres aplazar su render hasta que toque: DnzDeferredContent. Y si un bloque puede petar al renderizar, lo aislas para que no se lleve la pagina entera: DnzTryComponent. Elige por el momento, no por el aspecto.

Cual va en cada caso

La confusion habitual es entre "estoy procesando una accion" y "la interfaz aun no esta lista". No son lo mismo:

NecesitasUsaPor que
Avisar de que estas procesando: una seccion entera carga datos y aun no tienes nada que pintarDnzLoaderSpinner neutro centrado en el hueco mientras esperas a OnInitializedAsync
Avisar de que la UI aun no esta lista: reservar el hueco con la forma del contenido (lista, tarjeta, KPIs)DnzSkeletonEsqueleto animado: el usuario ya ve cuanto va a ocupar, asi la espera se siente mas corta
Aplazar el render de un bloque pesado para que la pagina respireDnzDeferredContentPinta primero un skeleton y monta el contenido real tras un delay; ideal para revelado progresivo
Que un componente que puede fallar no tumbe toda la paginaDnzTryComponentCaptura la excepcion de render y muestra un fallback en su lugar
Feedback de una accion concreta del usuario (un boton, 1-10s)IsBusy=@variable en el botonNo es de esta familia: el spinner vive en el propio boton

La regla rapida: DnzLoader = "estoy trabajando" (hay una operacion en curso). DnzSkeleton = "esto aun no esta" (la interfaz se esta montando). Si dudas, preguntate si hay datos viajando ahora mismo (loader) o si solo estas pintando el hueco a la espera (skeleton).


DnzLoader

Spinner neutro para cuando una seccion entera esta cargando datos y aun no tienes nada que pintar. Es el patron de "cargar en OnInitializedAsync y devolver pronto".

@if (Facturas.IsNull())
{
	<DnzLoader />
}
else
{
	<FacturasGridU Data=@Facturas />
}

@code {
	private List<FacturaDTO> Facturas { get; set; }

	protected override async Task OnInitializedAsync()
	{
		Facturas = await FacturasService.GetPendientesAsync();
	}
}

En barras o cabeceras estrechas, donde un spinner centrado no encaja, pasa Horizontal="true" para la variante compacta de puntos:

<div class="d-flex align-items-center gap-2">
	<span>Sincronizando</span>
	<DnzLoader Horizontal="true" />
</div>

Parametros

ParametroTipoPor defectoQue hace
Horizontalboolfalsefalse pinta el loader vertical centrado en el hueco; true usa la variante horizontal compacta (tira de puntos), util en barras o cabeceras estrechas

DnzSkeleton

Reserva el hueco con rectangulos animados que imitan la forma del contenido que va a llegar. A diferencia del loader, el usuario ve cuantas lineas y que tamano va a ocupar, asi que la espera se siente mas corta.

@if (Movimientos.IsNull())
{
	<DnzSkeleton Lines="5" Height="0.9rem" />
}
else
{
	<MovimientosListaU Data=@Movimientos />
}

Combina varios skeletons de distinto tamano para imitar un encabezado mas filas:

<DnzSkeleton Lines="1" Height="0.7rem" MaxWidth="55%" />
<DnzSkeleton Lines="2" Height="0.9rem" MaxWidth="100%" />

Parametros

ParametroTipoPor defectoQue hace
Linesint1Numero de rectangulos (lineas) que pinta. Ajustalo a las filas que esperas: una tarjeta 1, una lista 5, un formulario largo 20
Heightstring"1rem"Alto de cada linea. Sube a "80px" para simular una tarjeta o KPI
Radiusstring"0.25rem"Radio de las esquinas de cada rectangulo
MaxWidthstring"100%"Ancho maximo del bloque. Limitalo ("400px", "55%") cuando el skeleton no deba ocupar todo el ancho

DnzDeferredContent

Envuelve un bloque pesado y aplaza su montaje: durante el delay pinta un esqueleto y, pasado ese tiempo, monta el contenido real. Es la pieza clave para que paginas con muchas subvistas aparezcan rapido en lugar de bloquearse pintando todo de golpe.

<DnzDeferredContent DelayMs="300">
	<VentasPorMesGraficoU Data=@Resumen />
</DnzDeferredContent>

Por que importa para el rendimiento. En una pagina con muchas subvistas (un dashboard, una ficha con varias pestanas, un listado con tarjetas pesadas), Blazor intenta renderizar todo en el primer paso. Envolviendo cada bloque caro en un DnzDeferredContent con delays crecientes, lo importante sale ya y el resto llega escalonado: la pagina da sensacion de velocidad aunque el trabajo total sea el mismo.

Patron de revelado progresivo en un dashboard: los KPIs (lo importante) salen ya, las tarjetas pesadas llegan escalonadas.

<DnzDeferredContent DelayMs="0">
	<KpiSeccionU Data=@Kpis />
</DnzDeferredContent>

<DnzDeferredContent DelayMs="300">
	<RadzenCard>
		<VentasPorMesGraficoU Data=@Ventas />
	</RadzenCard>
</DnzDeferredContent>

<DnzDeferredContent DelayMs="600">
	<RadzenCard>
		<TopClientesTablaU Data=@TopClientes />
	</RadzenCard>
</DnzDeferredContent>

Si no te vale el skeleton por defecto, pasa tu propio indicador de carga en LoadingContent:

<DnzDeferredContent DelayMs="800" Class="p-3">
	<LineasFacturaU Data=@Lineas />
	<LoadingContent>
		<DnzLoader />
	</LoadingContent>
</DnzDeferredContent>

Parametros

ParametroTipoPor defectoQue hace
DelayMsint500Milisegundos antes de montar el contenido real. 0 pinta ya; usa valores crecientes (300, 600...) para escalonar secciones
ChildContentRenderFragmentEl contenido pesado que se aplaza. Es lo que pones entre las etiquetas del componente
LoadingContentRenderFragmentIndicador de carga a medida mientras espera. Si no lo pasas, usa un DnzSkeleton
Classstring""Clase CSS para el contenedor del estado de carga (p. ej. "p-3" para darle aire)

DnzDeferredContent aplaza el render, no la carga de datos. Si lo caro es la query, traela en OnInitializedAsync y combina con DnzLoader/DnzSkeleton. El diferido solo reparte el coste de pintar la interfaz, no el de ir a buscar los datos.


DnzTryComponent

Envuelve un bloque que puede petar al renderizar y captura la excepcion para que no se lleve la pagina entera. Es un ErrorBoundary con un fallback opcional a medida.

<DnzTryComponent>
	<GraficoExternoU Data=@Datos />
</DnzTryComponent>

Con fallback propio: el context es la Exception capturada, asi que puedes mostrar el motivo.

<DnzTryComponent>
	<ChildContent>
		<WidgetTercerosU Config=@Config />
	</ChildContent>
	<ErrorContent>
		<RadzenAlert AlertStyle="AlertStyle.Danger" ShowIcon="true">
			No se pudo cargar el widget: @context.Message
		</RadzenAlert>
	</ErrorContent>
</DnzTryComponent>

El componente expone un metodo Recover() por referencia (@ref) para reintentar el render tras un fallo, util si das al usuario un boton de "Reintentar":

<DnzTryComponent @ref="boundary">
	<ChildContent>
		<WidgetTercerosU Config=@Config />
	</ChildContent>
	<ErrorContent>
		<div class="d-flex flex-column align-items-center gap-2 p-3">
			<span>El widget fallo: @context.Message</span>
			<RadzenButton Text="Reintentar" Click=@(() => boundary.Recover()) />
		</div>
	</ErrorContent>
</DnzTryComponent>

@code {
	private DnzTryComponent boundary;
}

Parametros

ParametroTipoPor defectoQue hace
ChildContentRenderFragmentEl contenido que se renderiza dentro del limite de error. Obligatorio (EditorRequired)
ErrorContentRenderFragment<Exception>Fallback que se pinta si el ChildContent lanza una excepcion. El context es la Exception capturada. Si no lo pasas, no se muestra nada en su lugar

DnzTryComponent tiene tambien un metodo publico Recover() (accesible por @ref) que reintenta renderizar el ChildContent despues de un fallo. Combinalo con un boton "Reintentar" en tu ErrorContent.


Relacionado

On this page