Trực quan hoá các danh sách lớn bằng Angular CDK

Giúp các danh sách lớn phản hồi nhanh hơn bằng cách triển khai cuộn ảo.

Stephen Fluin
Stephen Fluin

Danh sách cuộn là một trong những mẫu giao diện người dùng phổ biến nhất hiện nay, cho dù đó là duyệt xem một trang thông tin cuộn vô hạn trên trang mạng xã hội yêu thích của bạn hay điều hướng trên trang tổng quan của doanh nghiệp. Khi danh sách cuộn trở nên rất dài (hàng trăm, hàng nghìn hoặc hàng trăm nghìn mục), hiệu suất của ứng dụng có thể bị ảnh hưởng.

Các danh sách lớn có thể tải chậm vì ứng dụng phải tải và hiển thị tất cả dữ liệu trước. Các thành phần hiển thị này cũng có thể hiển thị và điều hướng chậm vì mỗi mục trong danh sách có thể có dữ liệu đa dạng thức, nội dung đa phương tiện và chức năng.

Người dùng có thể gặp vấn đề khi tải hoặc cuộn trang, dẫn đến sự thất vọng và bỏ ngang trang.

Cuộn ảo trong Angular bằng Bộ công cụ phát triển thành phần

Cuộn ảo là kỹ thuật chính được dùng để giải quyết các vấn đề về tỷ lệ này. Tính năng cuộn ảo tạo cảm giác về một danh sách rất lớn (bằng cách cung cấp thanh cuộn có kích thước phù hợp) và khả năng điều hướng danh sách mà không yêu cầu ứng dụng lưu giữ toàn bộ danh sách trong bộ nhớ hoặc hiển thị danh sách đó trên trang.

Trong Angular, tính năng cuộn ảo được cung cấp bởi Bộ công cụ phát triển thành phần (CDK). Bằng cách sửa đổi cách bạn lặp lại qua các danh sách và cung cấp một vài tham số cấu hình bổ sung, tính năng cuộn ảo của CDK sẽ tự động quản lý việc kết xuất ảo của các danh sách, cải thiện hiệu suất và khả năng phản hồi của trang.

Thay vì hiển thị toàn bộ danh sách cùng một lúc, chỉ một nhóm nhỏ các mục vừa với màn hình (cùng với một vùng đệm nhỏ) được hiển thị. Khi người dùng di chuyển, một tập hợp con mới của các mục sẽ được tính toán và hiển thị, sử dụng lại DOM hiện có nếu muốn.

Phần còn lại của bài đăng này sẽ hướng dẫn cách thiết lập tính năng cuộn ảo cơ bản. Bạn có thể xem ví dụ đầy đủ về cách hoạt động trong ứng dụng mẫu này:

Thiết lập tính năng cuộn ảo

Trước tiên, hãy đảm bảo bạn đã cài đặt @angular/cdk bằng trình quản lý gói yêu thích của mình. Để cài đặt thẻ này bằng npm, hãy chạy lệnh này trong cửa sổ dòng lệnh:

npm install --save @angular/cdk

Thêm ScrollingModule vào ứng dụng

Khi đã cài đặt CDK, hãy nhập ScrollingModule (chịu trách nhiệm xử lý thao tác cuộn ảo) từ gói @angular/cdk/scrolling. Sau đó, hãy thêm tham số này vào mảng nhập của mô-đun:

import {ScrollingModule} from '@angular/cdk/scrolling';

...
imports: [
  ScrollingModule
...
]
...

Tạo khung nhìn

Để xem cách hoạt động của gói này, hãy thử tạo một thành phần có một danh sách đơn giản gồm các số từ 0 đến 99.999:

@Component({
  template: `<div *ngFor="let item of list">{{item}}</div>`
})
export class ScrollComponent {
  list = Array.from({length: 100000}).map((_, i) => i);
}

Khi hiển thị ứng dụng, trình duyệt phải hiển thị 100.000 phần tử <div> riêng lẻ. Điều này có thể chấp nhận được đối với các nút văn bản đơn giản, nhưng mọi độ phức tạp trong mẫu lặp lại sẽ không điều chỉnh theo tỷ lệ tốt và mọi trình nghe sự kiện sẽ được nhân lên đáng kể.

Để thêm tính năng cuộn ảo và tránh những vấn đề đó, bạn cần tạo một khung nhìn bằng cách gói danh sách trong phần tử <cdk-virtual-scroll-viewport>:

@Component({
  template: `<cdk-virtual-scroll-viewport>
    <div *ngFor="let item of list">{{item}}</div>
    </cdk-virtual-scroll-viewport>`
})
export class ScrollComponent {
  list = Array.from({length: 100000}).map((_, i) => i);
}

ScrollingModule hiển thị linh động các tập hợp con của danh sách, nên bạn phải chỉ định chiều cao của khung nhìn thông qua CSS tiêu chuẩn. Bạn cũng cần cung cấp gợi ý về nội dung của khung nhìn bằng cách chỉ định itemSize. Mô-đun này sử dụng thông tin này để xác định số lượng mục cần giữ lại trong DOM tại một thời điểm nhất định và cách hiển thị thanh cuộn có kích thước phù hợp.

@Component({
  template: `<cdk-virtual-scroll-viewport itemSize="18" style="height:80vh">
    <div *ngFor="let item of list">{{item}}</div>
    </cdk-virtual-scroll-viewport>`
})
export class ScrollComponent {
  list = Array.from({length: 100000}).map((_, i) => i);
}

Cuối cùng, hãy chuyển đổi *ngFor thành *cdkVirtualFor:

@Component({
  template: `<cdk-virtual-scroll-viewport itemSize="18" style="height:80vh">
    <div *cdkVirtualFor="let item of list">{{item}}</div>
    </cdk-virtual-scroll-viewport>`
})
export class ScrollComponent {
  list = Array.from({length: 100000}).map((_, i) => i);
}

Thay vì lặp lại toàn bộ danh sách, khung nhìn sẽ tự động xác định và lặp lại đúng tập hợp con của danh sách cho người dùng. Bây giờ, khi người dùng tải trang, CDK sẽ hiển thị một tập hợp con của danh sách vừa với màn hình (cộng với một chút bộ đệm) và mọi sự kiện cuộn trong khung nhìn sẽ tải và hiển thị tập hợp con thích hợp của danh sách:

CDK hiển thị các tập hợp con của danh sách khi người dùng cuộn.

Tìm hiểu thêm

Khả năng cuộn ảo của CDK còn đi xa hơn nhiều so với ví dụ cơ bản này. Trong ứng dụng mẫu, toàn bộ danh sách nằm trong bộ nhớ, nhưng danh sách này có thể được tìm nạp theo yêu cầu cho các ứng dụng phức tạp hơn. Bạn có thể tìm hiểu thêm về các chức năng khác của ScrollingModule và lệnh cdkVirtualOf bằng cách đọc về Scrolling trong tài liệu về CDK.

Hình ảnh chính của Mr Cup/Fabien Barral trên Unsplash.