Hiểu hơn về phân trang - pagination

Phân trang - một thành phần không thể thiếu trong các ứng dụng có lượng dữ liệu lớn. Tuy nhiên, bạn hiểu được bao nhiêu về nó?
Hiểu hơn về phân trang - pagination
Hiểu hơn về phân trang - pagination

Phân trang là gì?

Đơn giản nó là cách chúng ta chunk dữ liệu thành từng page nhỏ trong trường hợp lượng dữ liệu lớn và hầu như không thể hiển thị hết trên một trang.

Về phía backend, khi có quá nhiều mục cần tải sẽ làm quá tải hệ thống, gây ảnh hưởng tới kết nối của những người dùng khác. Đây là một vấn đề lớn về hiệu suất.

 

Các loại phân trang thường gặp

Theo kinh nghiệm sử dụng của mình thì mình chia pagination thành 3 loại.

1. Numbered pages

Hay còn gọi là phân trang có đánh số. Google Search đang sử dụng cách phân trang này.

google-pagination.png

Phân trang đánh số này thường được sử dụng trong trường hợp các dữ liệu thường không có sự thay đổi quá thường xuyên.

Khi bạn nói với ai đó "Ồ, tôi đang mở trang thứ 3" thì bạn đang mong muốn dữ liệu ở trang thứ 3 này nhất quán ở cả phía bạn và người khác.

Hình thức phân trang này cũng có cái lợi là người dùng sẽ biết được trang cuối cùng là bao nhiêu (mặc dù mình nghĩ chẳng bao giờ họ navigate tới tận trang cuối đó).

 

2. Sequential pages

Hay còn gọi là phân trang tuần tự.

sequential-pages.png

Thường sử dụng cho các trang web hay ứng dụng trên điện thoại do không gian nhỏ, hoặc khi mà dữ liệu người dùng thay đổi nhanh đến mức việc đánh số trang chẳng có ý nghĩa gì nữa.

 

3. Infinite scroll

Cuộn, cuộn, cuộn và cuộn.

Hình thức này kết hợp với Loading Skeleton tạo ảo giác trang của bạn rất dài, và nội dung được hiển thị liên tục.

Lúc này, người dùng không còn quan tâm tới việc đang ở trang nào, họ chỉ cần cuộn để có thêm nội dung.

Ví dụ đơn giản nhất là các trang Twitter, Facebook, Reddit, Tiktok...

reddit.png

Có vẻ như hầu hết các ứng dụng hiện đại ngày nay đều sử dụng cách 2 hoặc 3 (đôi khi kết hợp chúng với nhau) khi mà có càng nhiều thuật toán render dữ liệu người dùng thay đổi liên tục, điều này khiến cho việc đánh số trang càng ngày càng mất ý nghĩa.

Mặc dù cách phân trang đánh số thứ tự thường không hữu dụng mấy cho các ứng dụng hiện đại so với các mô hình phân trang còn lại, tuy nhiên nó lại là cách dễ triển khai nhất trong các hệ thống cơ sở dữ liệu :D

 

Numbered pages

Ai đã dùng SQL trước đây đều biết cách implement nó một cách đơn giản như sau:

// Chúng ta muốn load nội dung cho page thứ 3, giới hạn mỗi page 100 phần tử
// ==> Chúng ta cần load 100 phần tử, bắt đầu từ sau phần tử thứ 200
SELECT * FROM users ORDER BY id DESC LIMIT 100 OFFSET 200;

Khi bạn muốn biết tổng số phần tử của các trang, bạn có thể thực hiện thêm một câu truy vấn khác:

SELECT COUNT(*) AS total_items FROM users;

Khá là đơn giản đúng không :D

Nhiều ứng dụng vẫn sử dụng cách phân trang này cho dù nó không có bao nhiêu ý nghĩa. Thử nghĩ mà xem, bạn chỉ cần cung cấp 2 tham số skiplimit là xong chuyện.

Để triển khai với REST, bạn chỉ cần thêm 1 tham số page vào query params là xong (mặc định Laravel dùng cách này).

GET http://localhost:3008/users?page=2

Để triển khai với GraphQL cũng khá đơn giản:

{
  users(page: 2) {
    id
    name
    roles {
      id
      name
    }
  }
}

Hạn chế của việc đánh số trang

Đối với các nội dung tĩnh hoặc ít khi thay đổi, đánh số trang là phương pháp tuyệt vời. Nhưng đối với các ứng dụng hiện đại ngày nay, việc đánh số trang đã không còn phù hợp. Các items đôi khi được thêm vào hoặc dịch chuyển đi mất trong khi người dùng đang nhảy tới các trang khác nhau.

  • Bỏ qua một vài items quan trọng: đôi khi người dùng sẽ bỏ qua mất một vài mục quan trọng khi mà chúng được thêm vào hoặc chuyển đi trong khi người dùng đang nhảy qua các trang.
  • Hiển thị một mục 2 lần: tương tự, do nội dung giữa các trang có thể bị thay đổi khi chúng ta thêm vào hoặc xóa đi một vài items, người dùng có thể thường xuyên gặp tình trang nhìn thấy một số items nhiều lần.

 

Có một giải pháp nào tốt nhất không?

Thực ra, không có cách nào là tốt nhất cả. Cái bạn cần quan tâm là đối tượng sử dụng ứng dụng của bạn là ai, và lúc này bạn sẽ lựa chọn hướng xử lý tốt nhất về UX cho các đối tượng đó.

Như blog này của mình, dữ liệu đâu được bao nhiêu, vậy nên mình vẫn sử dụng cách đơn giản nhất là phân trang có đánh số :D.

Trên tất cả, cần có một sự cân bằng giữa việc đơn giản hoá quá trình thực hiện - cải thiện hiệu suất - cũng như UX đẹp mắt, dễ sử dụng.

Comments

Bài viết nổi bật

PHP là ngôn ngữ được sử dụng rộng rãi nhất trên thế giới trong lập trình web. Nó cũng bị ghét nhất. Nhưng tại sao nhiều developer lại ghét nó đến vậy? Hôm nay chúng ta hãy cùng tìm hiểu lý do xem chúng có thuyết phục không nhé ^_^
Dạo gần đây đi đâu cũng nghe nói về microservices, người người nhà nhà rục rịch chuyển dịch hệ thống sang microservices. Trước khi đưa ra sự so sánh, mình sẽ khái quát một chút về Monolith Application và MicroServices một chút cho các bạn chưa biết nắm rõ hơn nhé.
Lúc trước mình hay sử dụng cách này trên laptop phụ của mình, giờ mua license luôn rồi. Hôm nay mình xin chia sẻ cho bạn nào cần nhé.
JWT Tokens là một cách thức lưu trữ thông tin xác thực hiệu quả, nhưng làm cách nào để chúng ta có thể giúp chúng an toàn hơn? Có 2 cách thường dùng để lưu trữ JWT Tokens là LocalStorage và Cookies. Bây giờ chúng ta sẽ bắt đầu "mổ xẻ" các ưu - nhược điểm của mỗi loại nhé.
Có khá nhiều bạn đã yêu cầu mình một bài viết về Repository Design Pattern. Vậy mục đích của nó là gì? Nó có thực sự cần thiết cho ứng dụng của bạn hay không? Những điểm mạnh, điểm yếu của nó là gì? Chúng ta cùng đi sâu tìm hiểu qua bài viết này nhé.

Mục lục

Related posts

Triển khai Saga Pattern trong microservices với NodeJS và Choreography-Based Saga
Mô hình Saga đưa ra một giải pháp có cấu trúc để giải quyết thách thức này. Nó cung cấp một phương pháp có hệ thống để quản lý transaction qua nhiều microservices. Điều này giải quyết những phức tạp của các transaction phân tán và hoàn toàn tương thích với các nguyên tắc của kiến trúc microservices, được đặc trưng bởi sự kết nối lỏng lẻo và khả năng triển khai độc lập của các service.
Một API cho phép giao tiếp hai chiều giữa các ứng dụng phần mềm thông qua các requests. Một Webhook là một API nhẹ, hỗ trợ chia sẻ dữ liệu một chiều được kích hoạt bởi các events.
Một trong những câu hỏi được đặt thường xuyên nhất về TypeScript là liệu chúng ta nên sử dụng interface hay type. Câu trả lời cho câu hỏi này, giống như nhiều câu hỏi lập trình khác, là nó phụ thuộc vào tình hình cụ thể. Trong một số trường hợp, một cái có lợi thế rõ rệt hơn cái kia, nhưng trong nhiều trường hợp, chúng có thể thay thế cho nhau.
Đây là các types cơ bản nhưng cũng phổ biến nhất trong Typescript. Một số types khác phức tạp hơn cũng được xây dựng dựa trên những types cơ bản này.
Trong thế giới lập trình, trách nhiệm lớn nhất của chúng ta không phải chỉ làm cho code chạy được, mà còn phải đảm bảo rằng các đoạn code mà chúng ta viết có thể dễ dàng kiểm tra và bảo trì trong một khoảng thời gian dài.
Javascript là một thành phần không thể thiếu đối với frontend developers. Tuy nhiên, ngay từ lúc ra đời, nó đã tồn tại khá nhiều vấn đề cần khắc phục. Đó là lý do tại sao từ 2015 (ES6) tới 2021 (ES12) ra đời nhằm giúp Javascript trở nên tốt hơn.
Dạo này mình làm việc với mấy bạn trên github, thấy hay xài mấy từ viết tắt mà mình không hiểu lắm. Thôi thì tổng hợp lại một list các từ viết tắt hay dùng trong github luôn cho ai cần :D
Dạo gần đây đi đâu cũng nghe nói về microservices, người người nhà nhà rục rịch chuyển dịch hệ thống sang microservices. Trước khi đưa ra sự so sánh, mình sẽ khái quát một chút về Monolith Application và MicroServices một chút cho các bạn chưa biết nắm rõ hơn nhé.
Cách bỏ qua câu lệnh --set-upstream quen thuộc cho các con lười
Mình sẽ giới thiệu 2 cách để xóa một property trong Javascript Object. Một cách sử dụng mutable - toán tử delete, một cách còn lại là immutable - tính năng Object Restructuring.
Đây là một khái niệm rất quan trọng trong Functional Programming. Ở đây mình sẽ cho ví dụ dựa trên Javascript, cụ thể là TypeScript, do đó mình hi vọng các bạn đã có một số kiến thức nhất định về JS trước. Điều này sẽ giúp bạn nắm bắt nội dung bài viết dễ dàng hơn.

Tin mới nhất

Triển khai Saga Pattern trong microservices với NodeJS và Choreography-Based Saga
Mô hình Saga đưa ra một giải pháp có cấu trúc để giải quyết thách thức này. Nó cung cấp một phương pháp có hệ thống để quản lý transaction qua nhiều microservices. Điều này giải quyết những phức tạp của các transaction phân tán và hoàn toàn tương thích với các nguyên tắc của kiến trúc microservices, được đặc trưng bởi sự kết nối lỏng lẻo và khả năng triển khai độc lập của các service.
Một API cho phép giao tiếp hai chiều giữa các ứng dụng phần mềm thông qua các requests. Một Webhook là một API nhẹ, hỗ trợ chia sẻ dữ liệu một chiều được kích hoạt bởi các events.
Một trong những câu hỏi được đặt thường xuyên nhất về TypeScript là liệu chúng ta nên sử dụng interface hay type. Câu trả lời cho câu hỏi này, giống như nhiều câu hỏi lập trình khác, là nó phụ thuộc vào tình hình cụ thể. Trong một số trường hợp, một cái có lợi thế rõ rệt hơn cái kia, nhưng trong nhiều trường hợp, chúng có thể thay thế cho nhau.
Trong phần này, chúng ta sẽ tìm hiểu một số khái niệm cơ bản nhất về AWS là gì và một số lợi ích khi sử dụng AWS.
Trở thành một software developer hiệu suất cao không phải là điều dễ dàng. Điều này đòi hỏi bạn phải có kỹ năng và kiến thức về lập trình, cũng như cách tiếp cận và giải quyết các vấn đề phức tạp. Tuy nhiên, nếu bạn có chút kiên nhẫn và sự nỗ lực, bạn hoàn toàn có thể trở thành một developer tài năng và thành công.
Đây là các types cơ bản nhưng cũng phổ biến nhất trong Typescript. Một số types khác phức tạp hơn cũng được xây dựng dựa trên những types cơ bản này.
Trong thế giới lập trình, trách nhiệm lớn nhất của chúng ta không phải chỉ làm cho code chạy được, mà còn phải đảm bảo rằng các đoạn code mà chúng ta viết có thể dễ dàng kiểm tra và bảo trì trong một khoảng thời gian dài.
Thông tin được định nghĩa dưới dạng dữ liệu, kiến thức về thông tin, và trí tuệ về tri thức.
Phân trang - một thành phần không thể thiếu trong các ứng dụng có lượng dữ liệu lớn. Tuy nhiên, bạn hiểu được bao nhiêu về nó?
Javascript là một thành phần không thể thiếu đối với frontend developers. Tuy nhiên, ngay từ lúc ra đời, nó đã tồn tại khá nhiều vấn đề cần khắc phục. Đó là lý do tại sao từ 2015 (ES6) tới 2021 (ES12) ra đời nhằm giúp Javascript trở nên tốt hơn.
Dạo này mình làm việc với mấy bạn trên github, thấy hay xài mấy từ viết tắt mà mình không hiểu lắm. Thôi thì tổng hợp lại một list các từ viết tắt hay dùng trong github luôn cho ai cần :D
Triển khai Saga Pattern trong microservices với NodeJS và Choreography-Based Saga
Mô hình Saga đưa ra một giải pháp có cấu trúc để giải quyết thách thức này. Nó cung cấp một phương pháp có hệ thống để quản lý transaction qua nhiều microservices. Điều này giải quyết những phức tạp của các transaction phân tán và hoàn toàn tương thích với các nguyên tắc của kiến trúc microservices, được đặc trưng bởi sự kết nối lỏng lẻo và khả năng triển khai độc lập của các service.
Một API cho phép giao tiếp hai chiều giữa các ứng dụng phần mềm thông qua các requests. Một Webhook là một API nhẹ, hỗ trợ chia sẻ dữ liệu một chiều được kích hoạt bởi các events.
Một trong những câu hỏi được đặt thường xuyên nhất về TypeScript là liệu chúng ta nên sử dụng interface hay type. Câu trả lời cho câu hỏi này, giống như nhiều câu hỏi lập trình khác, là nó phụ thuộc vào tình hình cụ thể. Trong một số trường hợp, một cái có lợi thế rõ rệt hơn cái kia, nhưng trong nhiều trường hợp, chúng có thể thay thế cho nhau.
Đây là các types cơ bản nhưng cũng phổ biến nhất trong Typescript. Một số types khác phức tạp hơn cũng được xây dựng dựa trên những types cơ bản này.