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

Tăng khả năng phản hồi cho các danh sách lớn bằng cách triển khai chức năng 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 qua một nguồn cấp dữ liệu cuộn vô hạn trên trang mạng xã hội bạn yêu thích hay đang thao tác trên một 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.

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 mục này cũng có thể bị chậm khi kết xuất và điều hướng vì mỗi mục trong danh sách có thể chứa dữ liệu đa dạng thức, nội dung nghe nhì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 cảm giác thất vọng và bỏ ngang trang.

Cuộn ảo trong Angular bằng Bộ công cụ dành cho nhà 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. Thao tác cuộn ảo mang lại ấn tượng về một danh sách rất lớn (bằng cách cung cấp một 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 toàn bộ danh sách trong bộ nhớ hoặc hiển thị trên trang.

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

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

Phần còn lại của bài đăng này sẽ trình bày 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ài đặt bằng npm, hãy chạy lệnh sau trong cửa sổ dòng lệnh:

npm install --save @angular/cdk

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

Sau khi cài đặt CDK, hãy nhập ScrollingModule (xử lý thao tác cuộn ảo) từ gói @angular/cdk/scrolling. Sau đó, thêm đối tượng 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, hãy thử tạo một thành phần với một danh sách đơn giản 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 kết xuất ứng dụng, trình duyệt phải kết xuất 100.000 phần tử <div> riêng lẻ. Điều này có thể ổn đố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 tăng tỷ lệ hiệu quả 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 đề này, bạn cần tạo 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 tự động hiển thị 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 cho khung nhìn gợi ý về nội dung 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 qua toàn bộ danh sách, khung nhìn sẽ tự động xác định và lặp lại thông qua tập hợp con danh sách chính xác cho người dùng. Giờ đây, khi người dùng tải trang, CDK sẽ hiển thị tập hợp con của danh sách phù hợp với màn hình (cộng thêm một chút vùng đệ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 phù 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 cao cấp 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 đều có trong bộ nhớ nhưng danh sách có thể được tìm nạp theo yêu cầu đối với 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 thông tin về Scrolling trong tài liệu về CDK.

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