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< IIntersectionObserverProps > = (props) => { const cardRefs = useRef<(HTMLDivElement | null)[]>([]); // 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>Post {index}</h5> <img width={"200"} height={"150"} src={eachItem} /> </div> ))} </div> ); }; export default IntersectionObserverImplement;
目标是检测提要列表中的最后一个帖子(称为哨兵)何时与视口相交。一旦发生这种情况,就会加载并显示更多帖子。
一个。初始化状态和引用
const cardRefs = useRef<(HTMLDivElement | null)[]>([]); // 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
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>Post {index}</h5> <img width={"200"} height={"150"} src={eachItem} /> </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< IIntersectionObserverProps > = (props) => { const cardRefs = useRef<(HTMLDivElement | null)[]>([]); // 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>Post {index}</h5> <img width={"200"} height={"150"} src={eachItem} /> </div> ))} </div> ); }; export default IntersectionObserverImplement;
选项对象
const cardRefs = useRef<(HTMLDivElement | null)[]>([]); // 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
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>Post {index}</h5> <img width={"200"} height={"150"} src={eachItem} /> </div> ))} </div> );
IntersectionObserver 接受回调函数和之前定义的选项对象。
每当观察到的元素满足选项中指定的条件时,回调就会运行。
entries 参数是观察到的元素的数组。每个条目都包含有关元素是否相交(可见)的信息。
如果entry.isIntersecting为true,则意味着最后一张卡片现在可见:
- 使用 setListItems 将新项目添加到列表中。
- 取消观察当前元素(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 创建的所有观察者。
这确保了当组件卸载或重新渲染时,旧的观察者被清理。
每个阶段会发生什么?
1。用户滚动
当用户滚动时,最后一张卡片进入视图
2。路口观察者触发器
当最后一张牌的50%可见时,观察者的回调
运行。
3。添加项目
回调将新项目添加到列表中 (setListItems)。
4。重复
观察者与旧的最后一张卡断开连接并附加到
新的最后一张卡。
这就是我们如何使用 Intersection Observer.
实现无限滚动希望这对您有帮助:)
谢谢。
以上是Reactjs 教程:使用 Intersection Observer 进行无限滚动。的详细内容。更多信息请关注PHP中文网其他相关文章!

热AI工具

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

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

Undress AI Tool
免费脱衣服图片

Clothoff.io
AI脱衣机

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

热门文章

热工具

记事本++7.3.1
好用且免费的代码编辑器

SublimeText3汉化版
中文版,非常好用

禅工作室 13.0.1
功能强大的PHP集成开发环境

Dreamweaver CS6
视觉化网页开发工具

SublimeText3 Mac版
神级代码编辑软件(SublimeText3)

JavaScript是现代Web开发的基石,它的主要功能包括事件驱动编程、动态内容生成和异步编程。1)事件驱动编程允许网页根据用户操作动态变化。2)动态内容生成使得页面内容可以根据条件调整。3)异步编程确保用户界面不被阻塞。JavaScript广泛应用于网页交互、单页面应用和服务器端开发,极大地提升了用户体验和跨平台开发的灵活性。

Python和JavaScript开发者的薪资没有绝对的高低,具体取决于技能和行业需求。1.Python在数据科学和机器学习领域可能薪资更高。2.JavaScript在前端和全栈开发中需求大,薪资也可观。3.影响因素包括经验、地理位置、公司规模和特定技能。

如何在JavaScript中将具有相同ID的数组元素合并到一个对象中?在处理数据时,我们常常会遇到需要将具有相同ID�...

学习JavaScript不难,但有挑战。1)理解基础概念如变量、数据类型、函数等。2)掌握异步编程,通过事件循环实现。3)使用DOM操作和Promise处理异步请求。4)避免常见错误,使用调试技巧。5)优化性能,遵循最佳实践。

实现视差滚动和元素动画效果的探讨本文将探讨如何实现类似资生堂官网(https://www.shiseido.co.jp/sb/wonderland/)中�...

JavaScript的最新趋势包括TypeScript的崛起、现代框架和库的流行以及WebAssembly的应用。未来前景涵盖更强大的类型系统、服务器端JavaScript的发展、人工智能和机器学习的扩展以及物联网和边缘计算的潜力。

深入探讨console.log输出差异的根源本文将分析一段代码中console.log函数输出结果的差异,并解释其背后的原因。�...
