Catatan
Akses ke halaman ini memerlukan otorisasi. Anda dapat mencoba masuk atau mengubah direktori.
Akses ke halaman ini memerlukan otorisasi. Anda dapat mencoba mengubah direktori.
Catatan
Ini bukan versi terbaru dari artikel ini. Untuk rilis saat ini, lihat versi .NET 10 dari artikel ini.
Peringatan
Versi ASP.NET Core ini tidak lagi didukung. Untuk informasi selengkapnya, lihat Kebijakan Dukungan .NET dan .NET Core. Untuk rilis saat ini, lihat versi .NET 9 dari artikel ini.
Artikel ini menjelaskan cara menggunakan virtualisasi komponen di aplikasi ASP.NET Core Blazor .
Virtualisasi
Tingkatkan performa rendering komponen yang dirasakan dengan menggunakan dukungan virtualisasi bawaan dari kerangka kerja Blazor pada komponen Virtualize<TItem>. Virtualisasi adalah teknik untuk membatasi penyajian UI hanya pada bagian yang saat ini terlihat. Misalnya, virtualisasi sangat membantu ketika aplikasi harus merender daftar panjang item dan hanya subset item yang diperlukan untuk terlihat pada waktu tertentu.
Gunakan komponen Virtualize<TItem> ketika:
- Menampilkan sekumpulan item data dalam perulangan.
- Sebagian besar item tidak terlihat karena harus menggulir.
- Item yang dirender berukuran sama.
Saat pengguna menggulir ke titik arbitrer dalam Virtualize<TItem> daftar item komponen, komponen menghitung item yang terlihat untuk ditampilkan. Item yang tidak terlihat tidak ditampilkan.
Tanpa virtualisasi, daftar umum mungkin menggunakan perulangan C# foreach untuk merender setiap item dalam daftar. Dalam contoh berikut:
-
allFlightsadalah kumpulan penerbangan pesawat terbang. - Komponen
FlightSummarymenampilkan detail tentang setiap penerbangan. - Atribut arahan
@keymenjaga hubungan setiapFlightSummarykomponen dengan penerbangan yang dirender olehFlightIdpenerbangan.
<div style="height:500px;overflow-y:scroll">
@foreach (var flight in allFlights)
{
<FlightSummary @key="flight.FlightId" Details="@flight.Summary" />
}
</div>
Jika koleksi berisi ribuan penerbangan, pemrosesan penerbangan membutuhkan waktu lama dan pengguna mengalami penundaan UI yang terasa. Sebagian besar penerbangan berada di luar ketinggian elemen <div>, jadi sebagian besar dari mereka tidak terlihat.
Alih-alih merender seluruh daftar penerbangan sekaligus, ganti perulangan foreach dalam contoh sebelumnya dengan komponen Virtualize<TItem>.
Tentukan
allFlightssebagai sumber item tetap ke Virtualize<TItem>.Items. Hanya penerbangan yang terlihat saat ini yang dirender oleh komponen Virtualize<TItem>.Jika koleksi non-generik menyediakan item, misalnya kumpulan DataRow, ikuti panduan dalam bagian Delegasi Penyedia Item untuk menyediakan item.
Tentukan konteks untuk setiap penerbangan dengan
Contextparameter . Dalam contoh berikut,flightdigunakan sebagai konteks, yang menyediakan akses ke setiap anggota penerbangan.
<div style="height:500px;overflow-y:scroll">
<Virtualize Items="allFlights" Context="flight">
<FlightSummary @key="flight.FlightId" Details="@flight.Summary" />
</Virtualize>
</div>
Jika konteks tidak ditentukan dengan Context parameter , gunakan nilai context dalam templat konten item untuk mengakses setiap anggota penerbangan:
<div style="height:500px;overflow-y:scroll">
<Virtualize Items="allFlights">
<FlightSummary @key="context.FlightId" Details="@context.Summary" />
</Virtualize>
</div>
Komponen Virtualize<TItem> :
- Menghitung jumlah item yang akan dirender berdasarkan tinggi kontainer dan ukuran item yang dirender.
- Menghitung ulang dan merender item saat pengguna menggulir.
- Hanya mengambil potongan data dari API eksternal yang sesuai dengan wilayah yang saat ini terlihat, termasuk overscan, saat
ItemsProviderdigunakan alih-alihItems(lihat bagian Delegasi penyedia item).
Konten item untuk Virtualize<TItem> komponen dapat mencakup:
- HTML dan Razor kode biasa, seperti yang ditunjukkan contoh sebelumnya.
- Satu atau beberapa Razor komponen.
- Campuran komponen HTML/Razor dan Razor.
Perwakilan penyedia item
Jika Anda tidak ingin memuat semua item ke dalam memori atau koleksi bukan generik ICollection<T>, Anda dapat menentukan metode delegasi penyedia item ke parameter komponen Virtualize<TItem>.ItemsProvider yang secara asinkron mengambil item yang diminta sesuai permintaan. Dalam contoh berikut, metode LoadEmployees menyediakan item ke komponen Virtualize<TItem>.
<Virtualize Context="employee" ItemsProvider="LoadEmployees">
<p>
@employee.FirstName @employee.LastName has the
job title of @employee.JobTitle.
</p>
</Virtualize>
Penyedia item menerima ItemsProviderRequest, yang menentukan jumlah item yang diperlukan mulai dari indeks mulai tertentu. Penyedia item kemudian mengambil item yang diminta dari database atau layanan lain dan mengembalikannya sebagai ItemsProviderResult<TItem> bersama dengan jumlah total item. Penyedia item dapat memilih untuk mengambil item dengan setiap permintaan atau menyimpannya dalam cache sehingga tersedia dengan mudah.
Komponen Virtualize<TItem> hanya dapat menerima satu sumber item dari parameternya, jadi jangan mencoba menggunakan penyedia item secara bersamaan dan menetapkan koleksi ke Items. Ketika parameter komponen dikonfigurasi pada runtime, akan melemparkan InvalidOperationException jika keduanya ditetapkan.
Contoh berikut memuat karyawan dari EmployeeService (tidak ditampilkan). Bidang totalEmployees biasanya akan ditetapkan dengan memanggil metode pada layanan yang sama (misalnya, EmployeesService.GetEmployeesCountAsync) di tempat lain, seperti selama inisialisasi komponen.
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);
}
Dalam contoh berikut, kumpulan DataRow adalah koleksi non-generik, sehingga item provider delegate digunakan untuk virtualisasi.
<Virtualize Context="row" ItemsProvider="GetRows">
...
</Virtualize>
@code{
...
private ValueTask<ItemsProviderResult<DataRow>> GetRows(ItemsProviderRequest request) =>
new(new ItemsProviderResult<DataRow>(
dataTable.Rows.OfType<DataRow>().Skip(request.StartIndex).Take(request.Count),
dataTable.Rows.Count));
}
Virtualize<TItem>.RefreshDataAsync menginstruksikan komponen untuk meminta ulang data dari ItemsProvider. Ini berguna ketika data eksternal berubah. Biasanya tidak perlu memanggil RefreshDataAsync saat menggunakan Items.
RefreshDataAsync memperbarui data komponen Virtualize<TItem> tanpa menyebabkan penggambaran ulang. Jika RefreshDataAsync dipanggil dari penangan peristiwa atau metode siklus hidup komponen, tidak perlu memicu render karena render secara otomatis dipicu di akhir penangan peristiwa atau metode siklus hidup. Jika RefreshDataAsync dipicu secara terpisah dari tugas atau peristiwa latar belakang, seperti di delegasi berikut ForecastUpdated , panggil StateHasChanged untuk memperbarui UI di akhir tugas atau peristiwa latar belakang:
<Virtualize ... @ref="virtualizeComponent">
...
</Virtualize>
...
private Virtualize<FetchData>? virtualizeComponent;
protected override void OnInitialized()
{
WeatherForecastSource.ForecastUpdated += async () =>
{
await InvokeAsync(async () =>
{
await virtualizeComponent?.RefreshDataAsync();
StateHasChanged();
});
});
}
Dalam contoh sebelumnya:
- RefreshDataAsync dipanggil terlebih dahulu untuk mendapatkan data baru untuk Virtualize<TItem> komponen.
-
StateHasChangeddipanggil untuk merender ulang komponen.
Placeholder
Karena meminta item dari sumber data jarak jauh mungkin memakan waktu, Anda memiliki opsi untuk merender tempat penampung dengan konten item:
-
Placeholder Gunakan (
<Placeholder>...</Placeholder>) untuk menampilkan konten hingga data item tersedia. - Gunakan Virtualize<TItem>.ItemContent untuk mengatur templat item untuk daftar.
<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>
Isi kosong
EmptyContent Gunakan parameter untuk menyediakan konten ketika komponen telah dimuat dan Items kosong atau ItemsProviderResult<TItem>.TotalItemCount nol.
EmptyContent.razor:
@page "/empty-content"
<PageTitle>Empty Content</PageTitle>
<h1>Empty Content Example</h1>
<Virtualize Items="stringList">
<ItemContent>
<p>
@context
</p>
</ItemContent>
<EmptyContent>
<p>
There are no strings to display.
</p>
</EmptyContent>
</Virtualize>
@code {
private List<string>? stringList;
protected override void OnInitialized() => stringList ??= [];
}
@page "/empty-content"
<PageTitle>Empty Content</PageTitle>
<h1>Empty Content Example</h1>
<Virtualize Items="stringList">
<ItemContent>
<p>
@context
</p>
</ItemContent>
<EmptyContent>
<p>
There are no strings to display.
</p>
</EmptyContent>
</Virtualize>
@code {
private List<string>? stringList;
protected override void OnInitialized() => stringList ??= [];
}
OnInitialized Ubah metode lambda untuk melihat string tampilan komponen:
protected override void OnInitialized() =>
stringList ??= [ "Here's a string!", "Here's another string!" ];
Ukuran barang
Tinggi setiap item dalam piksel dapat diatur dengan Virtualize<TItem>.ItemSize (default: 50). Contoh berikut mengubah tinggi setiap item dari default 50 piksel menjadi 25 piksel:
<Virtualize Context="employee" Items="employees" ItemSize="25">
...
</Virtualize>
Komponen Virtualize<TItem> mengukur ukuran penyajian (tinggi) item individual setelah render awal terjadi. Gunakan ItemSize untuk memberikan ukuran item yang tepat terlebih dahulu untuk membantu kinerja render awal yang akurat dan untuk memastikan posisi gulir yang benar untuk pemuatan ulang halaman. Jika default ItemSize menyebabkan beberapa item dirender di luar tampilan yang terlihat saat ini, pengulangan rendering kedua akan dipicu. Untuk mempertahankan posisi gulir browser dengan benar dalam daftar virtual, render awal harus benar. Jika tidak, pengguna mungkin melihat item yang salah.
Jumlah overscan (pengaturan tampilan yang melebihi batas)
Virtualize<TItem>.OverscanCount menentukan berapa banyak item tambahan yang dirender sebelum dan sesudah area yang terlihat. Pengaturan ini membantu mengurangi frekuensi penyajian selama pengguliran. Namun, nilai yang lebih tinggi menghasilkan lebih banyak elemen yang dirender di halaman (default: 3). Contoh berikut mengubah jumlah overscan dari default tiga item menjadi empat item:
<Virtualize Context="employee" Items="employees" OverscanCount="4">
...
</Virtualize>
Perubahan Status
Saat membuat perubahan pada item yang dirender oleh Virtualize<TItem> komponen, panggil StateHasChanged untuk mengantre evaluasi ulang dan penyajian ulang komponen. Untuk informasi lebih lanjut, lihat perenderan komponen Razor ASP.NET Core.
Dukungan gulir keyboard
Untuk memungkinkan pengguna menggulir konten virtual menggunakan keyboard mereka, pastikan bahwa elemen virtual atau kontainer gulir itu sendiri dapat difokuskan. Jika Anda gagal mengambil langkah ini, pengguliran keyboard tidak berfungsi di browser berbasis Chromium.
Misalnya, Anda dapat menggunakan tabindex atribut pada kontainer gulir:
<div style="height:500px; overflow-y:scroll" tabindex="-1">
<Virtualize Items="allFlights">
<div class="flight-info">...</div>
</Virtualize>
</div>
Untuk mempelajari lebih lanjut tentang arti nilai tabindex, -1, 0, atau nilai lainnya, lihat tabindex.
Gaya canggih dan deteksi pergeseran
Komponen Virtualize<TItem> ini hanya dirancang untuk mendukung mekanisme tata letak elemen tertentu. Untuk memahami tata letak elemen mana yang bekerja dengan benar, berikut ini menjelaskan cara Virtualize mendeteksi elemen mana yang harus terlihat untuk ditampilkan di tempat yang benar.
Jika kode sumber Anda terlihat seperti berikut:
<div style="height:500px; overflow-y:scroll" tabindex="-1">
<Virtualize Items="allFlights" ItemSize="100">
<div class="flight-info">Flight @context.Id</div>
</Virtualize>
</div>
Pada runtime, Virtualize<TItem> komponen merender struktur DOM yang mirip dengan yang berikut ini:
<div style="height:500px; overflow-y:scroll" tabindex="-1">
<div style="height:1100px"></div>
<div class="flight-info">Flight 12</div>
<div class="flight-info">Flight 13</div>
<div class="flight-info">Flight 14</div>
<div class="flight-info">Flight 15</div>
<div class="flight-info">Flight 16</div>
<div style="height:3400px"></div>
</div>
Jumlah aktual baris yang dirender dan ukuran pengantara bervariasi sesuai dengan gaya dan ukuran Items koleksi Anda. Namun, perhatikan bahwa ada elemen spacer div yang disuntikkan sebelum dan sesudah konten Anda. Ini melayani dua tujuan:
- Untuk memberikan offset sebelum dan sesudah konten Anda, item yang saat ini terlihat akan muncul di lokasi yang benar dalam rentang gulir. Rentang gulir itu sendiri akan mewakili ukuran total semua konten.
- Untuk mendeteksi kapan pengguna menggulir melampaui batas tampilan saat ini, yang berarti konten berbeda harus dirender.
Catatan
Untuk mempelajari cara mengontrol tag elemen HTML spacer, lihat bagian Mengontrol nama tag elemen spacer nanti di artikel ini.
Elemen spacer secara internal menggunakan Intersection Observer untuk menerima pemberitahuan ketika mereka mulai terlihat.
Virtualize tergantung pada penerimaan peristiwa ini.
Virtualize bekerja dalam kondisi berikut:
Semua item konten yang dirender, termasuk konten placeholder, memiliki tinggi yang identik. Ini memungkinkan untuk menghitung konten mana yang sesuai dengan posisi gulir tertentu tanpa terlebih dahulu mengambil setiap item data dan merender data ke dalam elemen DOM.
Pemisa dan baris konten dirender dalam satu tumpukan vertikal dengan setiap item mengisi seluruh lebar horizontal. Dalam kasus penggunaan umum,
Virtualizebekerja dengandivelemen. Jika Anda menggunakan CSS untuk membuat tata letak yang lebih canggih, ingatlah persyaratan berikut:- Gaya kontainer gulir memerlukan
displaydengan salah satu nilai berikut:-
block(default untukdiv). -
table-row-group(default untuktbody). -
flexdenganflex-directiondiatur kecolumn. Pastikan bahwa turunan langsung dari komponen Virtualize<TItem> tidak menyusut di bawah aturan kelenturan. Misalnya, tambahkan.mycontainer > div { flex-shrink: 0 }.
-
- Gaya baris konten memerlukan
displaydengan salah satu nilai berikut:-
block(default untukdiv). -
table-row(default untuktr).
-
- Jangan gunakan CSS untuk mengganggu tata letak untuk elemen spacer. Elemen spacer memiliki nilai
displaysebesarblock, kecuali jika induknya adalah grup baris tabel, dalam hal ini, nilai default mereka menjaditable-row. Jangan mencoba memengaruhi lebar atau tinggi elemen spacer, termasuk dengan menyebabkannya memiliki batas ataucontentelemen pseudo.
- Gaya kontainer gulir memerlukan
Pendekatan apa pun yang menghentikan penyekat dan elemen konten ditampilkan sebagai tumpukan vertikal tunggal, atau menyebabkan variasi tinggi pada item konten, mencegah fungsi yang benar dari komponen Virtualize<TItem>.
Virtualisasi tingkat root
Komponen Virtualize<TItem> ini mendukung penggunaan dokumen itu sendiri sebagai akar gulir, sebagai alternatif untuk memiliki beberapa elemen lain dengan overflow-y: scroll. Dalam contoh berikut, elemen <html> atau <body> distilir dalam komponen menggunakan overflow-y: scroll.
<HeadContent>
<style>
html, body { overflow-y: scroll }
</style>
</HeadContent>
Komponen Virtualize<TItem> ini mendukung penggunaan dokumen itu sendiri sebagai akar gulir, sebagai alternatif untuk memiliki beberapa elemen lain dengan overflow-y: scroll. Saat menggunakan dokumen sebagai akar gulir, hindari menata elemen <html> atau <body> dengan overflow-y: scroll karena hal ini menyebabkan pengamat persimpangan memperlakukan tinggi halaman yang dapat digulir sepenuhnya sebagai wilayah yang terlihat, bukan hanya viewport jendela.
Anda dapat mereproduksi masalah ini dengan membuat daftar virtual besar (misalnya, 100.000 item) dan mencoba menggunakan dokumen sebagai akar gulir dengan html { overflow-y: scroll } di halaman gaya CSS. Meskipun mungkin berfungsi dengan benar pada beberapa kesempatan, browser mencoba memproses tampilan semua 100.000 item setidaknya satu kali pada awal penyajian, yang dapat menyebabkan penguncian tab browser.
Untuk mengatasi masalah ini sebelum rilis .NET 7, hindari elemen gaya <html>/<body> dengan overflow-y: scroll atau adopsi pendekatan alternatif. Dalam contoh berikut, tinggi elemen <html> diatur sedikit lebih dari 100% dari tinggi viewport.
<HeadContent>
<style>
html { min-height: calc(100vh + 0.3px) }
</style>
</HeadContent>
Komponen Virtualize<TItem> ini mendukung penggunaan dokumen itu sendiri sebagai akar gulir, sebagai alternatif untuk memiliki beberapa elemen lain dengan overflow-y: scroll. Saat menggunakan dokumen sebagai akar gulir, hindari menata elemen <html> atau <body> dengan overflow-y: scroll karena ini menyebabkan tinggi seluruh halaman yang dapat digulir dianggap sebagai area yang terlihat, bukan hanya viewport jendela.
Anda dapat mereproduksi masalah ini dengan membuat daftar virtual besar (misalnya, 100.000 item) dan mencoba menggunakan dokumen sebagai akar gulir dengan html { overflow-y: scroll } di halaman gaya CSS. Meskipun mungkin berfungsi dengan benar pada beberapa kesempatan, browser mencoba memproses tampilan semua 100.000 item setidaknya satu kali pada awal penyajian, yang dapat menyebabkan penguncian tab browser.
Untuk mengatasi masalah ini sebelum rilis .NET 7, hindari elemen gaya <html>/<body> dengan overflow-y: scroll atau adopsi pendekatan alternatif. Dalam contoh berikut, tinggi elemen <html> diatur sedikit lebih dari 100% dari tinggi viewport.
<style>
html { min-height: calc(100vh + 0.3px) }
</style>
Mengontrol nama tag elemen pengatur jarak
Virtualize<TItem> Jika komponen ditempatkan di dalam elemen yang memerlukan nama tag anak tertentu, SpacerElement memungkinkan Anda mendapatkan atau menetapkan nama tag spacer virtualisasi. Nilai defaultnya adalah div. Untuk contoh berikut, Virtualize<TItem> komponen dirender di dalam elemen bagian tubuh tabel (tbody), sehingga elemen turunan yang sesuai untuk baris tabel (tr) diatur sebagai pemisah.
VirtualizedTable.razor:
@page "/virtualized-table"
<PageTitle>Virtualized Table</PageTitle>
<HeadContent>
<style>
html, body {
overflow-y: scroll
}
</style>
</HeadContent>
<h1>Virtualized Table Example</h1>
<table id="virtualized-table">
<thead style="position: sticky; top: 0; background-color: silver">
<tr>
<th>Item</th>
<th>Another column</th>
</tr>
</thead>
<tbody>
<Virtualize Items="fixedItems" ItemSize="30" SpacerElement="tr">
<tr @key="context" style="height: 30px;" id="row-@context">
<td>Item @context</td>
<td>Another value</td>
</tr>
</Virtualize>
</tbody>
</table>
@code {
private List<int> fixedItems = Enumerable.Range(0, 1000).ToList();
}
Dalam contoh sebelumnya, akar dokumen digunakan sebagai kontainer gulir, sehingga elemen html dan body ditata dengan overflow-y: scroll. Untuk informasi selengkapnya, lihat sumber daya berikut:
ASP.NET Core