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廣泛應用於網頁交互、單頁面應用和服務器端開發,極大地提升了用戶體驗和跨平台開發的靈活性。

JavaScript的最新趨勢包括TypeScript的崛起、現代框架和庫的流行以及WebAssembly的應用。未來前景涵蓋更強大的類型系統、服務器端JavaScript的發展、人工智能和機器學習的擴展以及物聯網和邊緣計算的潛力。

不同JavaScript引擎在解析和執行JavaScript代碼時,效果會有所不同,因為每個引擎的實現原理和優化策略各有差異。 1.詞法分析:將源碼轉換為詞法單元。 2.語法分析:生成抽象語法樹。 3.優化和編譯:通過JIT編譯器生成機器碼。 4.執行:運行機器碼。 V8引擎通過即時編譯和隱藏類優化,SpiderMonkey使用類型推斷系統,導致在相同代碼上的性能表現不同。

JavaScript是現代Web開發的核心語言,因其多樣性和靈活性而廣泛應用。 1)前端開發:通過DOM操作和現代框架(如React、Vue.js、Angular)構建動態網頁和單頁面應用。 2)服務器端開發:Node.js利用非阻塞I/O模型處理高並發和實時應用。 3)移動和桌面應用開發:通過ReactNative和Electron實現跨平台開發,提高開發效率。

Python更適合初學者,學習曲線平緩,語法簡潔;JavaScript適合前端開發,學習曲線較陡,語法靈活。 1.Python語法直觀,適用於數據科學和後端開發。 2.JavaScript靈活,廣泛用於前端和服務器端編程。

本文展示了與許可證確保的後端的前端集成,並使用Next.js構建功能性Edtech SaaS應用程序。 前端獲取用戶權限以控制UI的可見性並確保API要求遵守角色庫

從C/C 轉向JavaScript需要適應動態類型、垃圾回收和異步編程等特點。 1)C/C 是靜態類型語言,需手動管理內存,而JavaScript是動態類型,垃圾回收自動處理。 2)C/C 需編譯成機器碼,JavaScript則為解釋型語言。 3)JavaScript引入閉包、原型鍊和Promise等概念,增強了靈活性和異步編程能力。

我使用您的日常技術工具構建了功能性的多租戶SaaS應用程序(一個Edtech應用程序),您可以做同樣的事情。 首先,什麼是多租戶SaaS應用程序? 多租戶SaaS應用程序可讓您從唱歌中為多個客戶提供服務
