Cách triển khai Infinite Scroll trong ứng dụng web

Infinite scroll - Cuộn vô hạn cho phép tải nội dung liên tục khi người dùng di chuyển xuống dưới trang, khác phương thức click để tải của căn trang truyền thống. Tính năng này có thể mang tới trải nghiệm mượt mà hơn, đặc biệt trên thiết bị mobile.

Cuộn vô hạn trong ứng dụng web

Hãy cùng Quantrimang.com khám phá cách thiết lập Infinite scroll đơn giản bằng HTML, CSS và JavaScript nhé!

Thiết lập frontend

Bắt đầu bằng cấu trúc HTML cơ bản để hiện nội dung. Dưới đây là một ví dụ:

<!DOCTYPE html>
<html>
<head>
    <link rel="stylesheet" href="style.css" />
</head>
<body>
    <h1>Trang cuộn vô hạn</h1>

    <div class="products__list">
      <img src="https://fakestoreapi.com/img/71li-ujtlUL._AC_UX679_.jpg"
           alt="Jacket" />

      <img src="https://fakestoreapi.com/img/71li-ujtlUL._AC_UX679_.jpg"
           alt="Jacket" />

      <img src="https://fakestoreapi.com/img/71li-ujtlUL._AC_UX679_.jpg"
           alt="Jacket" />

      <img src="https://fakestoreapi.com/img/71li-ujtlUL._AC_UX679_.jpg"
           alt="Jacket" />

      <img src="https://fakestoreapi.com/img/71li-ujtlUL._AC_UX679_.jpg"
           alt="Jacket" />

      <img src="https://fakestoreapi.com/img/71li-ujtlUL._AC_UX679_.jpg"
           alt="Jacket" />
    </div>

    <script src="script.js"></script>
</body>
</html>

Trang này chứa một chuỗi ảnh placeholder và tham chiếu hai nguồn: một file CSS và một file JavaScript.

Kiểu CSS cho nội dung có thể cuộn

Để hiện ảnh placeholder trong một khung kẻ ô, thêm CSS sau vào file style.css:

* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

html { font-size: 62.5%; }

body {
  font-family: Cambria, Times, "Times New Roman", serif;
}

h1 {
  text-align: center;
  font-size: 5rem;
  padding: 2rem;
}

img {
  width: 100%;
  display: block;
}

.products__list {
  display: flex;
  flex-wrap: wrap;
  gap: 2rem;
  justify-content: center;
}

.products__list > * {
  width: calc(33% - 2rem);
}

.loading-indicator {
  display: none;
  position: absolute;
  bottom: 30px;
  left: 50%;
  background: #333;
  padding: 1rem 2rem;
  color: #fff;
  border-radius: 10px;
  transform: translateX(-50%);
}

Hiện tại, trang của bạn trông sẽ như thế này:

Trang cuộn vô hạn

Triển khai cốt lõi với JS

Chỉnh sửa script.js. Để triển khai infinite scroll (cuộn vô hạn), bạn cần phát hiện thời điểm người dùng đã cuộn gần phía dưới cùng của container hoặc trang nội dung.

"use strict";

window.addEventListener("scroll", () => {
  if (
    window.scrollY + window.innerHeight >=
      document.documentElement.scrollHeight - 100
  ) {
    // Người dùng ở gần dưới cùng, tìm nạp nhiều nội dung hơn
    fetchMoreContent();
  }
});

Sau đó, tạo một hàm để tìm nạp nhiều dữ liệu placeholder hơn.

async function fetchMoreContent() {
  try {
    let response = await fetch("https://fakestoreapi.com/products?limit=3");

    if (!response.ok) {
      throw new Error("Network response was not ok");
    }

    let data = await response.json();
    console.log(data);
  } catch (error) {
    console.error("There was a problem fetching new content:", error);
  } finally {
    console.log("Fetch function fired");
  }
}

Đối với dự án này, bạn có thể dùng API từ fakestoreapi.

Để xác nhận dữ liệu được tìm nạp khi cuộn, hãy nhìn vào console:

Triển khai cốt lõi với JS

Bạn sẽ thấy dữ liệu được tìm nạp nhiều lần khi cuộn. Nó có thể là nhân tố ảnh hưởng tới hiệu suất của thiết bị. Để tránh điều này, tạo một trạng thái tìm nạp dữ liệu ban đầu:

let isFetching = false;

Sau đó, chỉnh sửa hàm tìm nạp để chỉ tìm dữ liệu sau một quá trình đã hoàn tất trước đó.

async function fetchMoreContent() {
  if (isFetching) return; // Thoát nếu tìm nạp dữ liệu đã xong

  isFetching = true; // Đặt flag sang true

  try {
    let response = await fetch("https://fakestoreapi.com/products?limit=3");

    if (!response.ok) {
      throw new Error("Network response was not ok");
    }

    let data = await response.json();
  } catch (error) {
    console.error("There was a problem fetching new content:", error);
  } finally {
    console.log("Fetch function fired");
    isFetching = false; // Reset flag sang false
  }
}

Hiện nội dung mới

Để hiện nội dung mới khi người dùng cuộn xuống dưới trang, tạo một hàm nối các hình ảnh vào container chính.

Đầu tiên, chọn thành phần chính:

const productsList = document.querySelector(".products__list");

Sau đó, tạo hàm nối thêm nội dung:

function displayNewContent(data) {
  data.forEach((item) => {
    const imgElement = document.createElement("img");
    imgElement.src = item.image;
    imgElement.alt = item.title;
    productsList.appendChild(imgElement); // Append to productsList container
  });
}

Cuối cùng, chỉnh sửa hàm tìm nạp và chuyển dữ liệu đã tìm nạp sang hàm bổ sung thêm.

async function fetchMoreContent() {
  if (isFetching) return;

  isFetching = true;

  try {
    let response = await fetch("https://fakestoreapi.com/products?limit=3");

    if (!response.ok) {
      throw new Error("Network response was not ok");
    }

    let data = await response.json();
    displayNewContent(data);
  } catch (error) {
    console.error("There was a problem fetching new content:", error);
  } finally {
    console.log("Fetch function fired");
    isFetching = false;
  }
}

Thế là xong, giờ cuộn vô hạn sẽ hoạt động.

Tính năng cuộn vô hạn sẽ hoạt động

Nâng cao cuộn vô hạn

Để nâng cao trải nghiệm người dùng, bạn có thể hiện một chỉ báo tải khi tìm nạp mới nội dung. Bắt đầu bằng cách thêm HTML này.

<h1 class="loading-indicator">Loading...</h1>

Sau đó chọn thành phần tải.

const loadingIndicator = document.querySelector(".loading-indicator");

Cuối cùng, tạo hai hàm bật/tắt khả năng hiển thị chỉ báo tải.

function showLoadingIndicator() {
  loadingIndicator.style.display = "block";
  console.log("Loading...");
}

function hideLoadingIndicator() {
  loadingIndicator.style.display = "none";
  console.log("Finished loading.");
}

Sau đó, thêm chúng vào hàm tìm nạp.

async function fetchMoreContent() {
  if (isFetching) return; // Exit if already fetching

  isFetching = true;
  showLoadingIndicator(); // Show loader

  try {
    let response = await fetch("https://fakestoreapi.com/products?limit=3");

    if (!response.ok) {
      throw new Error("Network response was not ok");
    }

    let data = await response.json();
    displayNewContent(data);
  } catch (error) {
    console.error("There was a problem fetching new content:", error);
  } finally {
    console.log("Fetch function fired");
    hideLoadingIndicator(); // Hide loader
    isFetching = false;
 }
}

Kết quả:

Kết quả sau khi kích hoạt cuộn vô hạn thành công

Những lưu ý khi dùng infinite scroll:

  • Không tìm nạp quá nhiều mục cùng lúc vì có thể làm giảm hiệu suất của trình duyệt.
  • Thay vì tìm nạp nội dung ngay lập tức sau khi phát hiện sự kiện cuộn, hãy dùng hàm gỡ lỗi để trì hoãn tìm nạp một chút. Điều này có thể ngăn chặn các truy vấn mạng quá mức.
  • Không phải tất cả người dùng đều thích cuộn vô hạn. Hãy cung cấp lựa chọn dùng thành phần phân trang nếu muốn.

Nếu không còn nhiều nội dung để tải, hãy thông báo cho người dùng thay vì liên tục cố gắng tìm nạp nhiều dữ liệu hơn.

Thứ Năm, 09/11/2023 09:59
51 👨 258
0 Bình luận
Sắp xếp theo