滾動是水平或垂直移動網頁上部分內容的使用者操作(在大多數情況下)。
就像您在閱讀本文時所做的那樣。
無限意味著當您向下捲動網頁時,新內容會自動載入。
好吧,但是為什麼每個人都應該實現它?
可發現性
讓我們想像一下您最喜歡的電子商務商店正在舉辦黑色星期五促銷活動。
您在探索頁面上找到了幾個產品,但當您滾動到網頁底部而不是更多產品時,您發現了一個按鈕,可將您帶到下一個產品列表。
您將能夠看到新產品(但前提是您注意到該操作按鈕)。
無限滾動只是幫助用戶找到更多他們可能錯過的內容。
為了實現無限滾動,我們需要檢查使用者是否到達頁面底部或容器。
但是偵測滾動的位置是非常昂貴的,並且由於不同的瀏覽器和設備,其位置值不可靠。
所以一個方法是觀看頁面的最後內容(元素)及其與視窗或容器的交點。
我們如何找到交點?
它是一個 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 儲存頁面上目前可見項目的陣列。
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 鍵。
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,則表示最後一張卡片現在可見:
觀察最後一張牌
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中文網其他相關文章!