Jak zaimplementować nieskończone przewijanie w aplikacji internetowej

Implementacja nieskończonego przewijania na stronie internetowej

Nieskończone przewijanie to mechanizm, który umożliwia dynamiczne doładowywanie treści w miarę przewijania strony przez użytkownika. Eliminuje potrzebę tradycyjnego podziału na strony z przyciskami nawigacyjnymi. Takie rozwiązanie zapewnia bardziej intuicyjną i płynną nawigację, zwłaszcza na urządzeniach mobilnych.

W niniejszym artykule omówimy, jak wdrożyć nieskończone przewijanie, wykorzystując podstawowe technologie internetowe: HTML, CSS i JavaScript.

Konfiguracja warstwy prezentacji

Pierwszym krokiem jest stworzenie szkieletu HTML, który będzie wyświetlał treść. Poniżej przedstawiono przykładowy kod:

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

Powyższy fragment przedstawia kontener, w którym umieszczone są przykładowe obrazy. Kod odwołuje się również do zewnętrznych arkuszy stylów CSS i plików JavaScript, które zostaną omówione w dalszej części artykułu.

Stylizacja CSS dla przewijalnej zawartości

Aby poprawnie wyświetlić elementy (w tym przypadku obrazki) w formie siatki, należy odpowiednio ostylować stronę za pomocą CSS. Poniższy kod powinien zostać umieszczony w pliku `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%);
        }
    

Dzięki tym stylom obrazki będą wyświetlane w trzech kolumnach, a dodatkowo dodany jest prosty styl dla wskaźnika ładowania.

W tym momencie strona powinna prezentować się podobnie do:

Logika nieskończonego przewijania w JavaScript

Kluczowym elementem wdrożenia nieskończonego przewijania jest kod JavaScript. Edytuj plik `script.js` i umieść w nim następujący kod:

          "use strict";

          window.addEventListener("scroll", () => {
            if (
              window.scrollY + window.innerHeight >=
                document.documentElement.scrollHeight - 100
            ) {
              fetchMoreContent();
            }
          });
      

Ten fragment kodu nasłuchuje zdarzenia przewijania strony i uruchamia funkcję `fetchMoreContent()`, gdy użytkownik zbliży się do dolnej krawędzi strony (dokładnie 100 pikseli przed jej końcem).

Kolejny kod dotyczy funkcji, która pobiera dane:

        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");
          }
        }
      

Funkcja ta pobiera z API fakestoreapi trzy nowe elementy (w tym przypadku są to produkty). W konsoli przeglądarki powinny pojawiać się pobrane dane.

Aby uniknąć nadmiernego obciążania serwera i przeglądarki poprzez wielokrotne wywoływanie funkcji pobierającej dane, warto wprowadzić dodatkową zmienną, która będzie informowała, czy aktualnie trwa pobieranie:

 let isFetching = false; 

Teraz należy zmodyfikować funkcję pobierającą dane, aby pobierała je dopiero po zakończeniu poprzedniej operacji:

       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();
            } catch (error) {
             console.error("There was a problem fetching new content:", error);
           } finally {
              console.log("Fetch function fired");
              isFetching = false;
            }
          }
    

Prezentacja pobranych danych

Po pobraniu danych konieczne jest ich wyświetlenie. W tym celu należy pobrać referencję do elementu nadrzędnego (kontenera), w którym umieszczane będą nowe obrazki:

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

Następnie należy stworzyć funkcję, która na podstawie pobranych danych wygeneruje elementy HTML i doda je do kontenera:

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

Ostatnim krokiem jest zmodyfikowanie funkcji `fetchMoreContent()` tak, aby po pobraniu danych przekazała je do funkcji `displayNewContent()`:

           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;
             }
          }
      

Po tych zmianach nieskończone przewijanie powinno działać prawidłowo, a nowe elementy będą pojawiać się w miarę przewijania strony.

Aby podnieść komfort użytkowania, warto dodać wskaźnik ładowania, który będzie informował użytkownika o trwającym procesie pobierania danych. Zacznijmy od dodania do HTML elementu wskaźnika:

<h1 class="loading-indicator">Ładowanie...</h1>

Następnie pobierzmy do niego referencję w JS:

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

Teraz stwórzmy dwie funkcje, które będą kontrolować widoczność wskaźnika:

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

          function hideLoadingIndicator() {
             loadingIndicator.style.display = "none";
             console.log("Zakończono ładowanie.");
          }
      

Na koniec zmodyfikuj funkcję `fetchMoreContent`, aby pokazywała wskaźnik na czas pobierania danych i ukrywała go po zakończeniu:

          async function fetchMoreContent() {
            if (isFetching) return;
             isFetching = true;
            showLoadingIndicator();
            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();
              isFetching = false;
             }
           }
        

Wprowadzone zmiany spowodują, że w trakcie ładowania nowych treści, użytkownik będzie widział wskaźnik „Ładowanie…”.

Warto pamiętać o kilku dobrych praktykach przy implementacji nieskończonego przewijania:

  • Unikaj pobierania zbyt dużej ilości danych na raz, gdyż może to negatywnie wpłynąć na wydajność przeglądarki.
  • Zastosuj funkcję opóźniającą (debounce) przy zdarzeniu przewijania, aby nie wysyłać zbyt wielu żądań w krótkim czasie.
  • Daj użytkownikowi wybór, czy chce korzystać z nieskończonego przewijania, czy tradycyjnej paginacji.
  • Poinformuj użytkownika, jeśli nie ma już więcej treści do załadowania.

Podsumowanie

Nieskończone przewijanie jest wygodnym rozwiązaniem, które ułatwia przeglądanie treści. Szczególnie sprawdza się w przypadku stron mobilnych. Wykorzystując omówione techniki i wskazówki, można łatwo wdrożyć tę funkcjonalność na swojej witrynie.

Zawsze należy pamiętać o perspektywie użytkownika i zapewnić mu informacje o aktualnym stanie działania aplikacji, np. poprzez wyświetlanie wskaźników ładowania czy komunikatów o błędach.


newsblog.pl