搜索
首页web前端js教程Reactjs 教程:使用 Intersection Observer 进行无限滚动。

什么是无限滚动以及它的必要性?

滚动是水平或垂直移动网页上部分内容的用户操作(在大多数情况下)。

就像您在阅读本文时所做的那样。

无限意味着当您向下滚动网页时,新内容会自动加载。

好吧,但是为什么每个人都应该实现它?

可发现性

让我们想象一下您最喜欢的电子商务商店正在举办黑色星期五促销活动。

您在探索页面上找到了几个产品,但当您滚动到网页底部而不是更多产品时,您发现了一个按钮,可将您带到下一个产品列表。

您将能够看到新产品(但前提是您注意到该操作按钮)。

无限滚动只是帮助用户找到更多他们可能错过的内容。

执行

为了实现无限滚动,我们需要检查用户是否到达页面底部或容器。

但是检测滚动的位置是非常昂贵的,并且由于不同的浏览器和设备,其位置值不可靠。

所以一种方法是观看页面的最后内容(元素)及其与视口或容器的交点

我们如何找到交点?

路口观察者

它是一个 Web API,允许观察内容或列表末尾的元素

当这个元素(“哨兵”)变得可见(与视口相交时,它会触发回调函数

通过这个函数我们可以获取更多数据并将其加载到网页中。

整个观察是异步发生的,这最小化对主线程的影响。


为了在 Reactjs 中实现 Intersection Observer,我们将以社交提要为例,我们将在帖子列表上进行无限滚动。

看一下这个组件,您就可以了解下面每个部分的详细情况。

import { useEffect, useRef, useState } from "react";

interface IIntersectionObserverProps {}

const allItems = [
  "https://picsum.photos/200",
  "https://picsum.photos/200",
  "https://picsum.photos/200",
  "https://picsum.photos/200",
];

const IntersectionObserverImplement: React.FunctionComponent = (props) => {
  const cardRefs = useRef([]); // Initialize as an empty array
  const containerRef = useRef<htmldivelement null>(null);
  const [listItems, setListItems] = useState(allItems);

  useEffect(() => {
    const options = {
      root: containerRef.current,
      rootMargin: "0px",
      threshold: 0.5,
    };
    const observer = new IntersectionObserver((entries, observer) => {
      entries.forEach((entry) => {
        if (entry.isIntersecting) {
          setListItems((prevItems) => [
            ...prevItems,
            "https://picsum.photos/200",
          ]);
          observer.unobserve(entry.target); // Stop observing the current element
        }
      });
    }, options);

    // Observe the last card only
    const lastCard = cardRefs.current[listItems.length - 1];

    if (lastCard) {
      observer.observe(lastCard);
    }

    return () => observer.disconnect(); // Clean up observer on unmount
  }, [listItems]);

  return (
    <div classname="container" ref="{containerRef}">
      {listItems.map((eachItem, index) => (
        <div classname="card" ref="{(el)"> (cardRefs.current[index] = el)} // Assign refs correctly
          key={index}
        >
          <h5 id="Post-index">Post {index}</h5>
          <img  src="/static/imghwm/default1.png" data-src="https://img.php.cn/upload/article/000/000/000/173443591411756.jpg?x-oss-process=image/resize,p_40" class="lazy"    style="max-width:90%"200"}' height='{"150"}' alt="Reactjs 教程:使用 Intersection Observer 进行无限滚动。" >
        </div>
      ))}
    </div>
  );
};

export default IntersectionObserverImplement;

</htmldivelement>

目标是检测提要列表中的最后一个帖子(称为哨兵)何时与视口相交。一旦发生这种情况,就会加载并显示更多帖子。


一个。初始化状态和引用
const cardRefs = useRef([]); // For storing references to each card
const containerRef = useRef<htmldivelement null>(null); // Reference to the scrollable container
const [listItems, setListItems] = useState(allItems); // State to hold the list of items

</htmldivelement>

cardRefs 一个数组,用于跟踪表示列表中卡片的 DOM 元素。

containerRef 指的是可滚动容器。

listItems 保存页面上当前可见项目的数组。

b.渲染列表并分配引用
return (
  <div classname="container" ref="{containerRef}">
    {listItems.map((eachItem, index) => (
      <div classname="card" ref="{(el)"> (cardRefs.current[index] = el)} // Assign a ref to each card
        key={index}
      >
        <h5 id="Post-index">Post {index}</h5>
        <img  src="/static/imghwm/default1.png" data-src="https://img.php.cn/upload/article/000/000/000/173443591411756.jpg?x-oss-process=image/resize,p_40" class="lazy"    style="max-width:90%"200"}' height='{"150"}' alt="Reactjs 教程:使用 Intersection Observer 进行无限滚动。" >
      </div>
    ))}
  </div>
);

containerRef 标记将发生滚动的容器。

cardRefs 为列表中的每张卡片分配一个参考。这确保我们可以告诉观察者要监视哪个元素(例如,最后一张卡片)。

映射 listItems 以呈现列表中的每个项目。
每个 div 都被设计成一张卡片,并且有一个唯一的 React 键。

c.观察最后一个帖子(项目)。
import { useEffect, useRef, useState } from "react";

interface IIntersectionObserverProps {}

const allItems = [
  "https://picsum.photos/200",
  "https://picsum.photos/200",
  "https://picsum.photos/200",
  "https://picsum.photos/200",
];

const IntersectionObserverImplement: React.FunctionComponent = (props) => {
  const cardRefs = useRef([]); // Initialize as an empty array
  const containerRef = useRef<htmldivelement null>(null);
  const [listItems, setListItems] = useState(allItems);

  useEffect(() => {
    const options = {
      root: containerRef.current,
      rootMargin: "0px",
      threshold: 0.5,
    };
    const observer = new IntersectionObserver((entries, observer) => {
      entries.forEach((entry) => {
        if (entry.isIntersecting) {
          setListItems((prevItems) => [
            ...prevItems,
            "https://picsum.photos/200",
          ]);
          observer.unobserve(entry.target); // Stop observing the current element
        }
      });
    }, options);

    // Observe the last card only
    const lastCard = cardRefs.current[listItems.length - 1];

    if (lastCard) {
      observer.observe(lastCard);
    }

    return () => observer.disconnect(); // Clean up observer on unmount
  }, [listItems]);

  return (
    <div classname="container" ref="{containerRef}">
      {listItems.map((eachItem, index) => (
        <div classname="card" ref="{(el)"> (cardRefs.current[index] = el)} // Assign refs correctly
          key={index}
        >
          <h5 id="Post-index">Post {index}</h5>
          <img  src="/static/imghwm/default1.png" data-src="https://img.php.cn/upload/article/000/000/000/173443591411756.jpg?x-oss-process=image/resize,p_40" class="lazy"    style="max-width:90%"200"}' height='{"150"}' alt="Reactjs 教程:使用 Intersection Observer 进行无限滚动。" >
        </div>
      ))}
    </div>
  );
};

export default IntersectionObserverImplement;

</htmldivelement>

选项对象

const cardRefs = useRef([]); // For storing references to each card
const containerRef = useRef<htmldivelement null>(null); // Reference to the scrollable container
const [listItems, setListItems] = useState(allItems); // State to hold the list of items

</htmldivelement>

root 指定滚动容器。

containerRef.current 指的是包裹所有卡片的 div。
如果 root 为 null,则默认观察视口。

rootMargin:定义根周围的额外边距。

“0px”表示没有多余的空间。您可以使用“100px”之类的值来提前触发观察者(例如,当元素即将出现时)。

阈值:确定观察者触发时目标元素必须可见的程度。

0.5 表示当最后一张卡片的 50% 可见时触发回调。

创建观察者

return (
  <div classname="container" ref="{containerRef}">
    {listItems.map((eachItem, index) => (
      <div classname="card" ref="{(el)"> (cardRefs.current[index] = el)} // Assign a ref to each card
        key={index}
      >
        <h5 id="Post-index">Post {index}</h5>
        <img  src="/static/imghwm/default1.png" data-src="https://img.php.cn/upload/article/000/000/000/173443591411756.jpg?x-oss-process=image/resize,p_40" class="lazy"    style="max-width:90%"200"}' height='{"150"}' alt="Reactjs 教程:使用 Intersection Observer 进行无限滚动。" >
      </div>
    ))}
  </div>
);

IntersectionObserver 接受回调函数和之前定义的选项对象。

每当观察到的元素满足选项中指定的条件时,回调就会运行。

entries 参数是观察到的元素的数组。每个条目都包含有关元素是否相交(可见)的信息。

如果entry.isIntersecting为true,则意味着最后一张卡片现在可见:

  1. 使用 setListItems 将新项目添加到列表中。
  2. 取消观察当前元素(entry.target)以防止冗余触发器。

观察最后一张牌

 useEffect(() => {
    const options = {
      root: containerRef.current,
      rootMargin: "0px",
      threshold: 0.5,
    };
    const observer = new IntersectionObserver((entries, observer) => {
      entries.forEach((entry) => {
        if (entry.isIntersecting) {
          setListItems((prevItems) => [
            ...prevItems,
            "https://picsum.photos/200",
          ]);
          observer.unobserve(entry.target); // Stop observing the current element
        }
      });
    }, options);

    // Observe each card
    const lastCard = cardRefs.current[listItems.length - 1];

    if (lastCard) {
      observer.observe(lastCard);
    }

    return () => observer.disconnect(); // Clean up observer on unmount
  }, [listItems]);

cardRefs.current:跟踪对所有卡片的引用。

listItems.length - 1:标识列表中的最后一项。

如果lastCard存在,使用observer.observe(lastCard)开始观察它。

观察者会监听这张卡片,并在它可见时触发回调。

清理

const options = {
  root: containerRef.current, // Observe within the container
  rootMargin: "0px",         // No margin around the root container
  threshold: 0.5,           // Trigger when 50% of the element is visible
};

observer.disconnect() 删除此 useEffect 创建的所有观察者。

这确保了当组件卸载或重新渲染时,旧的观察者被清理。


Reactjs Tutorial : Infinite scrolling with Intersection Observer.

每个阶段会发生什么?

1。用户滚动

当用户滚动时,最后一张卡片进入视图

2。路口观察者触发器

当最后一张牌的50%可见时,观察者的回调
运行。

3。添加项目

回调将新项目添加到列表中 (setListItems)。

4。重复

观察者与旧的最后一张卡断开连接并附加到
新的最后一张卡。

Reactjs Tutorial : Infinite scrolling with Intersection Observer.

这就是我们如何使用 Intersection Observer.

实现无限滚动

希望这对您有帮助:)

谢谢。

以上是Reactjs 教程:使用 Intersection Observer 进行无限滚动。的详细内容。更多信息请关注PHP中文网其他相关文章!

声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
JavaScript数据类型:浏览器和nodejs之间是否有区别?JavaScript数据类型:浏览器和nodejs之间是否有区别?May 14, 2025 am 12:15 AM

JavaScript核心数据类型在浏览器和Node.js中一致,但处理方式和额外类型有所不同。1)全局对象在浏览器中为window,在Node.js中为global。2)Node.js独有Buffer对象,用于处理二进制数据。3)性能和时间处理在两者间也有差异,需根据环境调整代码。

JavaScript评论:使用//和 / * * / * / * /JavaScript评论:使用//和 / * * / * / * /May 13, 2025 pm 03:49 PM

JavaScriptusestwotypesofcomments:single-line(//)andmulti-line(//).1)Use//forquicknotesorsingle-lineexplanations.2)Use//forlongerexplanationsorcommentingoutblocksofcode.Commentsshouldexplainthe'why',notthe'what',andbeplacedabovetherelevantcodeforclari

Python vs. JavaScript:开发人员的比较分析Python vs. JavaScript:开发人员的比较分析May 09, 2025 am 12:22 AM

Python和JavaScript的主要区别在于类型系统和应用场景。1.Python使用动态类型,适合科学计算和数据分析。2.JavaScript采用弱类型,广泛用于前端和全栈开发。两者在异步编程和性能优化上各有优势,选择时应根据项目需求决定。

Python vs. JavaScript:选择合适的工具Python vs. JavaScript:选择合适的工具May 08, 2025 am 12:10 AM

选择Python还是JavaScript取决于项目类型:1)数据科学和自动化任务选择Python;2)前端和全栈开发选择JavaScript。Python因其在数据处理和自动化方面的强大库而备受青睐,而JavaScript则因其在网页交互和全栈开发中的优势而不可或缺。

Python和JavaScript:了解每个的优势Python和JavaScript:了解每个的优势May 06, 2025 am 12:15 AM

Python和JavaScript各有优势,选择取决于项目需求和个人偏好。1.Python易学,语法简洁,适用于数据科学和后端开发,但执行速度较慢。2.JavaScript在前端开发中无处不在,异步编程能力强,Node.js使其适用于全栈开发,但语法可能复杂且易出错。

JavaScript的核心:它是在C还是C上构建的?JavaScript的核心:它是在C还是C上构建的?May 05, 2025 am 12:07 AM

javascriptisnotbuiltoncorc; saninterpretedlanguagethatrunsonenginesoftenwritteninc.1)javascriptwasdesignedAsalightweight,解释edganguageforwebbrowsers.2)Enginesevolvedfromsimpleterterterpretpreterterterpretertestojitcompilerers,典型地提示。

JavaScript应用程序:从前端到后端JavaScript应用程序:从前端到后端May 04, 2025 am 12:12 AM

JavaScript可用于前端和后端开发。前端通过DOM操作增强用户体验,后端通过Node.js处理服务器任务。1.前端示例:改变网页文本内容。2.后端示例:创建Node.js服务器。

Python vs. JavaScript:您应该学到哪种语言?Python vs. JavaScript:您应该学到哪种语言?May 03, 2025 am 12:10 AM

选择Python还是JavaScript应基于职业发展、学习曲线和生态系统:1)职业发展:Python适合数据科学和后端开发,JavaScript适合前端和全栈开发。2)学习曲线:Python语法简洁,适合初学者;JavaScript语法灵活。3)生态系统:Python有丰富的科学计算库,JavaScript有强大的前端框架。

See all articles

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

Video Face Swap

Video Face Swap

使用我们完全免费的人工智能换脸工具轻松在任何视频中换脸!

热门文章

热工具

螳螂BT

螳螂BT

Mantis是一个易于部署的基于Web的缺陷跟踪工具,用于帮助产品缺陷跟踪。它需要PHP、MySQL和一个Web服务器。请查看我们的演示和托管服务。

SecLists

SecLists

SecLists是最终安全测试人员的伙伴。它是一个包含各种类型列表的集合,这些列表在安全评估过程中经常使用,都在一个地方。SecLists通过方便地提供安全测试人员可能需要的所有列表,帮助提高安全测试的效率和生产力。列表类型包括用户名、密码、URL、模糊测试有效载荷、敏感数据模式、Web shell等等。测试人员只需将此存储库拉到新的测试机上,他就可以访问到所需的每种类型的列表。

SublimeText3汉化版

SublimeText3汉化版

中文版,非常好用

EditPlus 中文破解版

EditPlus 中文破解版

体积小,语法高亮,不支持代码提示功能

Atom编辑器mac版下载

Atom编辑器mac版下载

最流行的的开源编辑器