如何在 Web 应用程序中实现无限滚动

与传统分页的点击加载方法不同,无限滚动可以让内容在用户向下移动页面时连续加载。 此功能可以提供更流畅的体验,尤其是在移动设备上。

了解如何使用纯 HTML、CSS 和 JavaScript 设置无限滚动。

设置前端

从基本的 HTML 结构开始显示您的内容。 这是一个例子:

 <!DOCTYPE html>
<html>
<head>
    <link rel="stylesheet" href="https://wilku.top/how-to-implement-infinite-scroll-in-a-web-application/style.css" />
</head>
<body>
    <h1>Infinite Scroll Page</h1>

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

    <script src="https://wilku.top/how-to-implement-infinite-scroll-in-a-web-application/script.js"></script>
</body>
</html>

此页面包含一系列占位符图像并引用两个资源:CSS 文件和 JavaScript 文件。

可滚动内容的 CSS 样式

要在网格中显示占位符图像,请将以下 CSS 添加到 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%);
}

目前,您的页面应如下所示:

  用于双因素身份验证的 9 个最佳硬件安全密钥 [2023]

JS 核心实现

编辑 script.js。 要实现无限滚动,您需要检测用户何时滚动到内容容器或页面底部附近。

 "use strict";

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

然后,创建一个函数来获取更多占位符数据。

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

对于此项目,您可以使用以下 API: 假商店API

要确认您的数据正在滚动获取,请查看控制台:

您会注意到您的数据在滚动时被多次获取,这可能是损害设备性能的一个因素。 为了防止这种情况,创建数据的初始获取状态:

 let isFetching = false; 

然后,修改您的获取函数,使其仅在上一次获取完成后获取数据。

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

显示新内容

要在用户向下滚动页面时显示新内容,请创建一个将图像附加到父容器的函数。

  TextNow 是匿名的吗?

首先,选择父元素:

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

然后,创建一个函数来附加内容。

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

最后,修改您的获取函数并将获取的数据传递给追加函数。

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

这样,你的无限滚动现在就可以工作了。

为了增强用户体验,您可以在获取新内容时显示加载指示器。 首先添加此 HTML。

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

然后选择加载元素。

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

最后,创建两个函数来切换加载指示器的可见性。

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

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

然后,将它们添加到 fetch 函数中。

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

这使:

  “FTFY”是什么意思,你如何使用它?

需要遵循的一些最佳实践包括:

  • 不要同时获取太多物品。 这可能会压垮浏览器并降低性能。
  • 不要在检测到滚动事件后立即获取内容,而是使用去抖动函数稍微延迟获取。 这可以防止过多的网络请求。
  • 并非所有用户都喜欢无限滚动。 如果需要,提供使用分页组件的选项。
  • 如果没有更多内容可供加载,请通知用户,而不是不断尝试获取更多内容。

掌握无缝内容加载

无限滚动让用户可以流畅地浏览内容,这对于使用移动设备的人来说非常有用。 如果您使用本文中的提示和重要建议,您可以将此功能添加到您的网站中。

请记住考虑用户在使用您的网站时的感受。 显示进度标志和错误注释等内容,以确保用户知道发生了什么。