Mempercepat Pengubahan MatTable dalam Beberapa Langkah

Sering terjadi bahwa sebagian besar aplikasi terdiri dari berbagai daftar dan tabel. Agar tidak menemukan kembali roda setiap saat, saya, seperti banyak orang, sering menggunakan tabel Material Sudut .

Kemudian, tabel ini tumbuh, baik data teks dan elemen bersarang ditempatkan di sel. Semua ini tumbuh dan menjadi beban yang baik pada mesin pengguna. Dan tentu saja, tidak ada yang suka ini.

Dalam proyek rumah terakhir saya, ada sebuah meja yang sel-selnya sebagian besar diisi dengan berbagai bidang (Anda bahkan bisa mengatakan bahwa itu adalah satu bentuk besar).

Dan rendering butuh sekitar 8 detik (tabel 40 x 40).

Jadi bagaimana Anda bisa mengoptimalkan MatTable untuk daftar besar?

gambar

Kasus cobaan


Untuk membantu orang lain mengatasi masalah ini, saya menulis aplikasi uji kecil. Semua tabel MatTable yang sama, dengan lima kolom (yang pertama adalah id elemen, sisanya adalah bidang teks MatFormField biasa).



Tampaknya itu adalah meja yang sederhana, tetapi bahkan mengubah alur dari tabel semacam itu tidak membutuhkan waktu tidak lebih atau kurang dari 2 detik (Oh, materi ini dan kinerja "top" -nya).



Proses rendering sendiri dalam hal ini hanya membutuhkan waktu (860 ms), namun, halaman membeku selama 2,2 detik dan pengguna merasa kesal.

Baiklah, mari kita coba membuat tabel dengan 300 baris. Dan drum roll, kami menunggu sedikit dan kami melihat bahwa hampir 10 detik dihabiskan untuk scripting dan rendering total. Artinya, dalam kasus ketika pengguna ingin menampilkan tabel seperti itu dalam 300 baris, halamannya akan membeku selama 10 detik. Ini sangat menakutkan dan menakjubkan (sebenarnya tidak).



Bahkan, saya masih mencoba untuk mengukur waktu yang diperlukan untuk menggambar 1000 elemen, tapi i7 saya yang menyedihkan tidak tahan dan halamannya terus jatuh.
Kami akan mencoba melakukan ini nanti dengan solusi yang sudah diterapkan.

Solusi untuk masalah tersebut


Jadi, setiap orang dapat melakukan pengukuran menggunakan utilitas berbasis browser, tetapi tidak ada solusi untuk masalah ini.

Keputusan ini menuntun saya dengan memikirkan esensi masalah.
pemahaman yang benar tentang masalah sudah setidaknya setengah dari solusinya.
Saya pikir semua orang mengerti bahwa ini terjadi karena data tabel pertama kali diproses oleh skrip dan kemudian dimuntahkan dalam keadaan utuh . Pada gilirannya, inilah tepatnya mengapa kita melihat suspensi yang khas.

Masalah ditemukan. Sekarang tinggal mencari tahu bagaimana menyelesaikannya. Solusi pertama yang terlintas dalam pikiran adalah yang paling sederhana. Jika masalah memproses semua data sekaligus, maka Anda perlu membuat tabel memproses data dalam bagian-bagian.

Tetapi bagaimana cara melakukannya?

Mari kita pikirkan apa yang kita miliki untuk ini di luar kotak. Hal pertama yang terlintas dalam pikiran adalah fungsi Track By. Saat mengubah sumber data, seluruh tabel tidak akan dirender ulang, tetapi hanya perubahannya.

Mari kita tambahkan fungsi ini ke tabel kita:

<mat-table [trackBy]="trackByFn" [dataSource]="commonDataSource">

Ya, tapi kami tidak memiliki kondisi sedemikian rupa sehingga data tabelnya entah bagaimana berubah, dan ini bukanlah pembicaraan sekarang. Tetapi bagaimana jika kita menulis Pipe, yang, ketika menginisialisasi sumber data, akan memecah data dan memberikannya ke tabel dalam batch. Pada gilirannya, fungsi trackBy akan membantu menghindari penyaji penuh.

@Pipe({
  name: 'splitSchedule'
})
export class SplitPipe implements PipeTransform {
  public transform(value: any, takeBy: number = 4, throttleTime: number = 40): Observable<Array<any>> {
    return Array.isArray(value)
      ? this.getSplittedThread(value, takeBy, throttleTime)
      : of(value);
  }

  private getSplittedThread(data: Array<any>, takeBy: number, throttleTime: number): Observable<Array<any>> {
    const repeatNumber = Math.ceil(data.length / takeBy);
    return timer(0, throttleTime).pipe(
      map((current) => data.slice(0, takeBy * ++current)),
      take(repeatNumber)
    );
  }
}

Berikut ini adalah sepotong kecil kode yang akan membantu perangkat keras Anda membuat tabel besar tersebut.

Terapkan pipa ini ke sumber data kami.


<mat-table [trackBy]="trackByFn"
           [dataSource]="commonDataSource | splitSchedule | async">

Sekarang mari kita coba melakukan pengukuran. Jadikan 100, 300, dan 1000 elemen.







Dan apa yang kita lihat? Apa yang benar-benar sukses bukanlah yang kami harapkan:

  • 300 elemen menjadikan 1 detik lebih cepat
  • 1000 diberikan dalam 11 detik dan tab tidak mati
  • dan 100 elemen umumnya menghasilkan 150 ms lebih lama

Tapi jangan buru-buru menarik kesimpulan, mari kita lihat dulu perilaku halaman dalam kedua kasus.





Seperti yang Anda lihat, dalam kasus biasa, halaman membeku selama beberapa detik dan pengguna tidak dapat melakukan apa-apa saat ini, saat menggunakan pipa kami dengan tautan ke trackBy memberi pengguna inisialisasi tabel hampir seketika dan tidak menyebabkan ketidaknyamanan saat menggunakan aplikasi.

Semoga artikel ini membantu seseorang.

Kode sumber untuk aplikasi tes ada di Stack Blitz .

All Articles