Virtualización de componentes de ASP.NET Core Blazor
Mejore el rendimiento percibido de la representación de componentes usando la compatibilidad de virtualización integrada del marco Blazor con el componente Virtualize. La virtualización es una técnica para limitar la representación de la interfaz de usuario a únicamente las partes visibles actualmente. Por ejemplo, la virtualización es útil cuando la aplicación debe representar una lista larga de elementos y solo es necesario que haya un subconjunto de elementos visible en un momento dado.
Use el componente Virtualize en las siguientes situaciones:
- La representación de un conjunto de elementos de datos en un bucle.
- La mayoría de los elementos no están visibles debido al desplazamiento.
- Los elementos representados tienen el mismo tamaño.
Cuando el usuario se desplaza a un punto arbitrario en la lista de elementos del componente Virtualize, este calcula los elementos visibles que se van a mostrar. Los elementos no visibles no se representan.
Sin la virtualización, una lista típica podría usar un bucle foreach de C# para representar cada elemento de una lista. En el ejemplo siguiente:
allFlightses una colección de vuelos de avión.- El componente
FlightSummarymuestra detalles sobre cada vuelo. - El atributo de directiva
@keyconserva la relación de cada componenteFlightSummarycon el vuelo representado según el elementoFlightIddel vuelo.
<div style="height:500px;overflow-y:scroll">
@foreach (var flight in allFlights)
{
<FlightSummary @key="flight.FlightId" Details="@flight.Summary" />
}
</div>
Si la colección contiene miles de vuelos, la representación de los vuelos tardará mucho tiempo y los usuarios experimentarán un retraso apreciable en la interfaz de usuario. La mayoría de los vuelos no se ven porque quedan fuera del alto del elemento <div>.
En lugar de representar la lista de vuelos completa de una vez, reemplace el bucle foreach del ejemplo anterior por el componente Virtualize:
- Especifique
allFlightscomo origen de elemento fijo en Virtualize<TItem>.Items. El componenteVirtualizerepresenta únicamente los vuelos actualmente visibles. - Especifique un contexto para cada vuelo con el parámetro
Context. En el siguiente ejemplo se usa como contextoflight, que proporciona acceso a los miembros de cada vuelo.
<div style="height:500px;overflow-y:scroll">
<Virtualize Items="@allFlights" Context="flight">
<FlightSummary @key="flight.FlightId" Details="@flight.Summary" />
</Virtualize>
</div>
Si no se especifica un contexto con el parámetro Context, use el valor de context en la plantilla de contenido del elemento para acceder a los miembros de cada vuelo:
<div style="height:500px;overflow-y:scroll">
<Virtualize Items="@allFlights">
<FlightSummary @key="context.FlightId" Details="@context.Summary" />
</Virtualize>
</div>
El componente Virtualize:
- Calcula el número de elementos que se van a representar en función del alto del contenedor y del tamaño de los elementos representados.
- Vuelve a calcular los elementos y los representa a medida que el usuario se desplaza.
- Solo captura el segmento de registros de una API externa que se corresponde a la región visible actual, en lugar de descargar todos los datos de la colección.
El contenido del elemento para el componente Virtualize puede incluir lo siguiente:
- HTML sin formato y código Razor, tal como se muestra en el ejemplo anterior.
- Uno o más componentes Razor.
- Una combinación de componentes HTML/Razor y Razor.
Delegado de proveedor de elementos
Si no se quieren cargar todos los elementos en la memoria, se puede especificar un método de delegado de proveedor de elementos en el parámetro Virtualize<TItem>.ItemsProvider del componente, que recupera de manera asincrónica los elementos solicitados a petición. En el ejemplo siguiente, el método LoadEmployees proporciona los elementos al componente Virtualize:
<Virtualize Context="employee" ItemsProvider="@LoadEmployees">
<p>
@employee.FirstName @employee.LastName has the
job title of @employee.JobTitle.
</p>
</Virtualize>
El proveedor de elementos recibe un objeto ItemsProviderRequest, que especifica el número necesario de elementos empezando por un índice de inicio específico. Luego, el proveedor de elementos recupera los elementos solicitados de una base de datos u otro servicio y los devuelve como un objeto ItemsProviderResult<TItem> junto con un recuento total de elementos. El proveedor de elementos puede elegir entre recuperar los elementos con cada solicitud o almacenarlos en la memoria caché para que estén disponibles fácilmente.
Un componente Virtualize solo puede aceptar un origen de elementos de sus parámetros, por lo que no intente usar simultáneamente un proveedor de elementos y asignar una colección a Items. Si se asignan ambos, se genera una clase InvalidOperationException cuando los parámetros del componente se establecen en tiempo de ejecución.
En el ejemplo del método LoadEmployees siguiente se cargan empleados de EmployeeService (no se muestra):
private async ValueTask<ItemsProviderResult<Employee>> LoadEmployees(
ItemsProviderRequest request)
{
var numEmployees = Math.Min(request.Count, totalEmployees - request.StartIndex);
var employees = await EmployeesService.GetEmployeesAsync(request.StartIndex,
numEmployees, request.CancellationToken);
return new ItemsProviderResult<Employee>(employees, totalEmployees);
}
Virtualize<TItem>.RefreshDataAsync indica al componente que vuelva a solicitar datos de su elemento ItemsProvider. Esto resulta útil cuando cambian los datos externos. No es necesario llamar a RefreshDataAsync cuando se usa Items.
Marcador de posición
Como la solicitud de elementos de un origen de datos remoto puede tardar tiempo, tiene la opción de representar un marcador de posición con contenido de los elementos:
- Use una instancia de Placeholder (
<Placeholder>...</Placeholder>) para mostrar el contenido hasta que los datos del elemento estén disponibles. - Use Virtualize<TItem>.ItemContent para establecer la plantilla de elemento de la lista.
<Virtualize Context="employee" ItemsProvider="@LoadEmployees">
<ItemContent>
<p>
@employee.FirstName @employee.LastName has the
job title of @employee.JobTitle.
</p>
</ItemContent>
<Placeholder>
<p>
Loading…
</p>
</Placeholder>
</Virtualize>
Tamaño del elemento
El alto de cada elemento en píxeles se puede establecer con Virtualize<TItem>.ItemSize (valor predeterminado: 50). En el siguiente ejemplo, el alto de cada elemento se cambia del valor predeterminado de 50 píxeles a 25 píxeles:
<Virtualize Context="employee" Items="@employees" ItemSize="25">
...
</Virtualize>
De forma predeterminada, el componente Virtualize mide el tamaño de representación (alto) de cada elemento después de que se produzca la representación inicial. Use ItemSize para proporcionar de antemano un tamaño de elemento exacto, con el fin de permitir un rendimiento de representación inicial preciso y garantizar la posición de desplazamiento correcta para las recargas de páginas. Si el valor predeterminado de ItemSize hace que algunos elementos se representen fuera de la vista actualmente visible, se desencadena una segunda representación. Para mantener correctamente la posición de desplazamiento del explorador en una lista virtualizada, la representación inicial debe ser correcta. De lo contrario, los usuarios podrían ver elementos incorrectos.
Recuento de sobrebarridos
Virtualize<TItem>.OverscanCount determina el número de elementos adicionales que se representan antes y después del área visible. Esta configuración ayuda a reducir la frecuencia de representación durante el desplazamiento. Pese a esto, unos valores superiores hacen que se representen más elementos en la página (valor predeterminado: 3). En el siguiente ejemplo se cambia el recuento de sobrebarridos del valor predeterminado de tres elementos a cuatro elementos:
<Virtualize Context="employee" Items="@employees" OverscanCount="4">
...
</Virtualize>
Cambios de estado
Al realizar cambios en los elementos representados por el componente Virtualize, llame a StateHasChanged para forzar que el componente vuelva a evaluarse y representarse. Para obtener más información, vea Representación de componentes de Blazor de ASP.NET Core.
Mejore el rendimiento percibido de la representación de componentes usando la compatibilidad de virtualización integrada del marco Blazor con el componente Virtualize. La virtualización es una técnica para limitar la representación de la interfaz de usuario a únicamente las partes visibles actualmente. Por ejemplo, la virtualización es útil cuando la aplicación debe representar una lista larga de elementos y solo es necesario que haya un subconjunto de elementos visible en un momento dado.
Use el componente Virtualize en las siguientes situaciones:
- La representación de un conjunto de elementos de datos en un bucle.
- La mayoría de los elementos no están visibles debido al desplazamiento.
- Los elementos representados tienen el mismo tamaño.
Cuando el usuario se desplaza a un punto arbitrario en la lista de elementos del componente Virtualize, este calcula los elementos visibles que se van a mostrar. Los elementos no visibles no se representan.
Sin la virtualización, una lista típica podría usar un bucle foreach de C# para representar cada elemento de una lista. En el ejemplo siguiente:
allFlightses una colección de vuelos de avión.- El componente
FlightSummarymuestra detalles sobre cada vuelo. - El atributo de directiva
@keyconserva la relación de cada componenteFlightSummarycon el vuelo representado según el elementoFlightIddel vuelo.
<div style="height:500px;overflow-y:scroll">
@foreach (var flight in allFlights)
{
<FlightSummary @key="flight.FlightId" Details="@flight.Summary" />
}
</div>
Si la colección contiene miles de vuelos, la representación de los vuelos tardará mucho tiempo y los usuarios experimentarán un retraso apreciable en la interfaz de usuario. La mayoría de los vuelos no se ven porque quedan fuera del alto del elemento <div>.
En lugar de representar la lista de vuelos completa de una vez, reemplace el bucle foreach del ejemplo anterior por el componente Virtualize:
- Especifique
allFlightscomo origen de elemento fijo en Virtualize<TItem>.Items. El componenteVirtualizerepresenta únicamente los vuelos actualmente visibles. - Especifique un contexto para cada vuelo con el parámetro
Context. En el siguiente ejemplo se usa como contextoflight, que proporciona acceso a los miembros de cada vuelo.
<div style="height:500px;overflow-y:scroll">
<Virtualize Items="@allFlights" Context="flight">
<FlightSummary @key="flight.FlightId" Details="@flight.Summary" />
</Virtualize>
</div>
Si no se especifica un contexto con el parámetro Context, use el valor de context en la plantilla de contenido del elemento para acceder a los miembros de cada vuelo:
<div style="height:500px;overflow-y:scroll">
<Virtualize Items="@allFlights">
<FlightSummary @key="context.FlightId" Details="@context.Summary" />
</Virtualize>
</div>
El componente Virtualize:
- Calcula el número de elementos que se van a representar en función del alto del contenedor y del tamaño de los elementos representados.
- Vuelve a calcular los elementos y los representa a medida que el usuario se desplaza.
- Solo captura el segmento de registros de una API externa que se corresponde a la región visible actual, en lugar de descargar todos los datos de la colección.
El contenido del elemento para el componente Virtualize puede incluir lo siguiente:
- HTML sin formato y código Razor, tal como se muestra en el ejemplo anterior.
- Uno o más componentes Razor.
- Una combinación de componentes HTML/Razor y Razor.
Delegado de proveedor de elementos
Si no se quieren cargar todos los elementos en la memoria, se puede especificar un método de delegado de proveedor de elementos en el parámetro Virtualize<TItem>.ItemsProvider del componente, que recupera de manera asincrónica los elementos solicitados a petición. En el ejemplo siguiente, el método LoadEmployees proporciona los elementos al componente Virtualize:
<Virtualize Context="employee" ItemsProvider="@LoadEmployees">
<p>
@employee.FirstName @employee.LastName has the
job title of @employee.JobTitle.
</p>
</Virtualize>
El proveedor de elementos recibe un objeto ItemsProviderRequest, que especifica el número necesario de elementos empezando por un índice de inicio específico. Luego, el proveedor de elementos recupera los elementos solicitados de una base de datos u otro servicio y los devuelve como un objeto ItemsProviderResult<TItem> junto con un recuento total de elementos. El proveedor de elementos puede elegir entre recuperar los elementos con cada solicitud o almacenarlos en la memoria caché para que estén disponibles fácilmente.
Un componente Virtualize solo puede aceptar un origen de elementos de sus parámetros, por lo que no intente usar simultáneamente un proveedor de elementos y asignar una colección a Items. Si se asignan ambos, se genera una clase InvalidOperationException cuando los parámetros del componente se establecen en tiempo de ejecución.
En el ejemplo del método LoadEmployees siguiente se cargan empleados de EmployeeService (no se muestra):
private async ValueTask<ItemsProviderResult<Employee>> LoadEmployees(
ItemsProviderRequest request)
{
var numEmployees = Math.Min(request.Count, totalEmployees - request.StartIndex);
var employees = await EmployeesService.GetEmployeesAsync(request.StartIndex,
numEmployees, request.CancellationToken);
return new ItemsProviderResult<Employee>(employees, totalEmployees);
}
Virtualize<TItem>.RefreshDataAsync indica al componente que vuelva a solicitar datos de su elemento ItemsProvider. Esto resulta útil cuando cambian los datos externos. No es necesario llamar a RefreshDataAsync cuando se usa Items.
Marcador de posición
Como la solicitud de elementos de un origen de datos remoto puede tardar tiempo, tiene la opción de representar un marcador de posición con contenido de los elementos:
- Use una instancia de Placeholder (
<Placeholder>...</Placeholder>) para mostrar el contenido hasta que los datos del elemento estén disponibles. - Use Virtualize<TItem>.ItemContent para establecer la plantilla de elemento de la lista.
<Virtualize Context="employee" ItemsProvider="@LoadEmployees">
<ItemContent>
<p>
@employee.FirstName @employee.LastName has the
job title of @employee.JobTitle.
</p>
</ItemContent>
<Placeholder>
<p>
Loading…
</p>
</Placeholder>
</Virtualize>
Tamaño del elemento
El alto de cada elemento en píxeles se puede establecer con Virtualize<TItem>.ItemSize (valor predeterminado: 50). En el siguiente ejemplo, el alto de cada elemento se cambia del valor predeterminado de 50 píxeles a 25 píxeles:
<Virtualize Context="employee" Items="@employees" ItemSize="25">
...
</Virtualize>
De forma predeterminada, el componente Virtualize mide el tamaño de representación (alto) de cada elemento después de que se produzca la representación inicial. Use ItemSize para proporcionar de antemano un tamaño de elemento exacto, con el fin de permitir un rendimiento de representación inicial preciso y garantizar la posición de desplazamiento correcta para las recargas de páginas. Si el valor predeterminado de ItemSize hace que algunos elementos se representen fuera de la vista actualmente visible, se desencadena una segunda representación. Para mantener correctamente la posición de desplazamiento del explorador en una lista virtualizada, la representación inicial debe ser correcta. De lo contrario, los usuarios podrían ver elementos incorrectos.
Recuento de sobrebarridos
Virtualize<TItem>.OverscanCount determina el número de elementos adicionales que se representan antes y después del área visible. Esta configuración ayuda a reducir la frecuencia de representación durante el desplazamiento. Pese a esto, unos valores superiores hacen que se representen más elementos en la página (valor predeterminado: 3). En el siguiente ejemplo se cambia el recuento de sobrebarridos del valor predeterminado de tres elementos a cuatro elementos:
<Virtualize Context="employee" Items="@employees" OverscanCount="4">
...
</Virtualize>
Cambios de estado
Al realizar cambios en los elementos representados por el componente Virtualize, llame a StateHasChanged para forzar que el componente vuelva a evaluarse y representarse. Para obtener más información, vea Representación de componentes de Blazor de ASP.NET Core.