云南做網(wǎng)站多少錢市場調(diào)研方案怎么寫
IntersectionObserver 基礎(chǔ)
IntersectionObserver 可以監(jiān)聽一個元素和可視區(qū)域相交部分的比例,然后在可視比例達到某個閾值的時候觸發(fā)回調(diào)。比如可以用來處理圖片的懶加載等等
首先我們來看下基本的格式:
const observer = new IntersectionObserver(callback, [options]);
相關(guān)的API屬性和方法:
直接看他的Typescript結(jié)構(gòu)吧
interface IntersectionObserver {// root 屬性用來獲取當(dāng)前 intersectionObserver 實例的根元素readonly root: Element | Document | null;readonly rootMargin: string;readonly thresholds: ReadonlyArray<number>;disconnect(): void;observe(target: Element): void;takeRecords(): IntersectionObserverEntry[];unobserve(target: Element): void;
}
root
: 如果構(gòu)造函數(shù)未傳入 root
或其值為null
,則默認使用頂級當(dāng)前文檔的視口。
rootMargin
: 是 IntersectionObserver
構(gòu)造函數(shù)的一個可選屬性,它定義了一個矩形區(qū)域,用于擴展或縮小root
元素的可視區(qū)域,從而影響intersectionRatio
的計算
const observer = new IntersectionObserver(entries => {// 處理entries},{root: document.querySelector('#scrollArea'), // 根元素 || 頂級當(dāng)前文檔rootMargin: '50px 20px 30px 10px' // 上右下左}
);
thresholds
:,它定義了一個監(jiān)聽交叉變化時觸發(fā)回調(diào)的閾值列表。這些閾值是介于0和1之間的數(shù)值,包括0和1,表示目標元素與根元素相交的比例。舉個例子,當(dāng)創(chuàng)建一個IntersectionObserver
實例時,你可以指定一個或多個閾值。例如,如果你想要在目標元素至少有25%、50%和75%可見時觸發(fā)回調(diào),你可以這樣設(shè)置thresholds
const observer = new IntersectionObserver(entries => {// 處理entries},{thresholds: [0, 0.25, 0.5, 0.75, 1]}
);
disconnect
用于停止監(jiān)聽目標元素與根元素的交叉變化。當(dāng)你不再需要觀察元素的可見性變化時,可以調(diào)用disconnect
方法來停止IntersectionObserver
的所有活動。
調(diào)用disconnect
方法后,IntersectionObserver
將不再觸發(fā)任何回調(diào),即使目標元素的可見性發(fā)生變化。這意味著,你已經(jīng)不再對目標元素的可見性感興趣,或者你想要在組件卸載時清理資源。
// 創(chuàng)建一個IntersectionObserver實例
const observer = new IntersectionObserver(function(entries) {// 處理交叉變化entries.forEach(function(entry) {if (entry.isIntersecting) {console.log('元素現(xiàn)在可見');} else {console.log('元素不再可見');}});
});// 開始觀察一個元素
const target = document.querySelector('#my-element');
observer.observe(target);// ...一段時間后...// 停止觀察元素
observer.disconnect();
observer
: 用于開始監(jiān)聽一個目標元素與根元素的交叉變化。當(dāng)你想要知道一個元素是否進入了視口(即用戶的可見區(qū)域)時,你可以使用observe
方法來指定需要觀察的元素
// 創(chuàng)建一個IntersectionObserver實例
const observer = new IntersectionObserver(function(entries) {// 處理交叉變化entries.forEach(function(entry) {if (entry.isIntersecting) {console.log('元素現(xiàn)在可見');} else {console.log('元素不再可見');}});
});// 獲取要觀察的元素
const target = document.querySelector('#my-element');// 開始觀察元素
observer.observe(target);
takeRecords
:用于獲取并清空IntersectionObserver
實例的記錄隊列。這個方法返回一個IntersectionObserverEntry
對象的數(shù)組,每個對象描述了目標元素的相交狀態(tài)
unobserve
:用于停止監(jiān)聽特定目標元素與根元素的交叉變化。當(dāng)你不再需要監(jiān)聽某個元素的可見性變化時,你可以使用unobserve
方法來停止對該元素的觀察。
綜合案例,實現(xiàn)圖片的懶加載
下面的方法使用的react,可以做必要的安裝哦!
下面是一個設(shè)置一個組件,看如下代碼
/** @Date: 2024-05-28 09:59:48* @Description: 組件的設(shè)計*/
import { CSSProperties, FC, ReactNode, useEffect, useRef, useState } from "react";interface MyLazyloadProps {className?: string; /* className 和 style 是給外層 div 添加樣式的 */style?: CSSProperties;placeholder?: ReactNode; /* 是占位的內(nèi)容 */offset?: string | number; /* 是距離到可視區(qū)域多遠就觸發(fā)加載 */width?: number | string;height?: string | number;onContentVisible?: () => void; /* 進入可視化區(qū)域后所產(chǎn)生的回調(diào) */children: ReactNode;
}const MyLazyload: FC<MyLazyloadProps> = (props) => {const { className = "", style, offset = 0, width, onContentVisible, placeholder, height, children } = props;const containerRef = useRef<HTMLDivElement>(null);const [visible, setVisible] = useState(false);const elementObserver = useRef<IntersectionObserver>();/* 關(guān)鍵函數(shù)去判斷可視范圍 */const lazyLoadHandler = (entries: IntersectionObserverEntry[]) => {const [entry] = entries;const { isIntersecting, intersectionRatio } = entry;if (intersectionRatio > 0) {const node = containerRef.current;console.log(node, entry, intersectionRatio);}if (isIntersecting) {setVisible(true);/* 可以通過這一層函數(shù)傳遞給外部,然后通過這個函數(shù),可以在外部組件做相對應(yīng)的處理等等 */onContentVisible?.();const node = containerRef.current;// 展示完成后及時的銷毀if (node && node instanceof HTMLElement) {elementObserver.current?.unobserve(node);}}}useEffect(() => {const options = {/* 這邊沒有寫root,則這邊的根元素就是此文檔的 containerRef *//* rootMargin 這邊做了一次偏移處理 */rootMargin: typeof offset === 'number' ? `${offset}px` : offset || '0px',/* 設(shè)置 threshold 為 0 也就是一進入可視區(qū)域就觸發(fā) */threshold: 0,}elementObserver.current = new IntersectionObserver(lazyLoadHandler, options);const node = containerRef.current; // 拿到nodeif (node instanceof HTMLElement) {elementObserver.current.observe(node);}return () => {if (node && node instanceof HTMLElement) {elementObserver.current?.unobserve(node);}}}, []);const styles = { height, width, ...style };return (<div ref={containerRef} className={`${className}`} style={styles}>{visible ? children : placeholder}</div>);
};export default MyLazyload;
組件的調(diào)用:
/** @Date: 2024-05-27 11:21:07* @Description: 組件的調(diào)用*/
import { useState } from "react";
import img1 from "./素材1.png";
import img2 from "./撲克牌1.jpg";
import "./App.css";
// import LazyLoad from 'react-lazyload';
import LazyLoad from "./MyLazyLoad";function App() {const [isVisible, setIsVisible] = useState<boolean>(false);return (<div><p>一一一一一一一一一一一一一一一一一一</p><p>一一一一一一一一一一一一一一一一一一</p><p>一一一一一一一一一一一一一一一一一一</p><p>一一一一一一一一一一一一一一一一一一</p><p>一一一一一一一一一一一一一一一一一一</p><p>一一一一一一一一一一一一一一一一一一</p><p>一一一一一一一一一一一一一一一一一一</p><p>一一一一一一一一一一一一一一一一一一</p><p>一一一一一一一一一一一一一一一一一一</p><p>一一一一一一一一一一一一一一一一一一</p><p>一一一一一一一一一一一一一一一一一一</p><p>一一一一一一一一一一一一一一一一一一</p><p>一一一一一一一一一一一一一一一一一一</p><p>一一一一一一一一一一一一一一一一一一</p><p>一一一一一一一一一一一一一一一一一一</p><p>一一一一一一一一一一一一一一一一一一</p><p>一一一一一一一一一一一一一一一一一一</p><p>一一一一一一一一一一一一一一一一一一</p><p>一一一一一一一一一一一一一一一一一一</p><p>一一一一一一一一一一一一一一一一一一</p><p>一一一一一一一一一一一一一一一一一一</p><p>一一一一一一一一一一一一一一一一一一</p><p>一一一一一一一一一一一一一一一一一一</p><p>一一一一一一一一一一一一一一一一一一</p><p>一一一一一一一一一一一一一一一一一一</p><p>一一一一一一一一一一一一一一一一一一</p><p>一一一一一一一一一一一一一一一一一一</p><p>一一一一一一一一一一一一一一一一一一</p><p>一一一一一一一一一一一一一一一一一一</p>{/* 這邊增加一些類名可以做一些的動畫 */}<LazyLoadclassName={isVisible ? "show" : "hide"}placeholder={<div>loading...</div>}onContentVisible={() => {console.log("comp visible");setIsVisible(true);}}>{/* <img src={img1}/> */}</LazyLoad><LazyLoadplaceholder={<div>loading...</div>}onContentVisible={() => {console.log("img visible");}}><img src={img2} /></LazyLoad></div>);
}export default App;
我們看最后的效果:
當(dāng)剛進入頁面的時候,我們下面的元素都處于 loading中,也是上面的placeholder的占位內(nèi)容。
當(dāng)滑動圖片的位置的時候才加載出相對應(yīng)的圖片地址和對應(yīng)的類名