這篇“怎么使用React+TS+IntersectionObserver實現視頻懶加載和自動播放功能”文章的知識點大部分人都不太理解,所以小編給大家總結了以下內容,內容詳細,步驟清晰,具有一定的借鑒價值,希望大家閱讀完這篇文章能有所收獲,下面我們一起來看看這篇“怎么使用React+TS+IntersectionObserver實現視頻懶加載和自動播放功能”文章吧。
IntersectionObserver 是瀏覽器內置的 API,用于監聽元素是否交叉或超出了視口(viewport)的變化。這個 API 提供了一種異步觀察目標元素的機制,在元素進入或離開視口時觸發回調函數。
以下是 IntersectionObserver API 的基本語法:
const observer = new IntersectionObserver(callback, options);
其中 callback
是回調函數,options
是配置選項,用于指定觀察器的參數,如視口的大小、元素與視口的交叉比例等。
創建 IntersectionObserver 對象后,我們就可以監聽目標元素:
observer.observe(target); // target 是被觀察的目標元素
組件卸載時,應取消監聽:
observer.unobserve(target);
如果監聽了多個元素,可以停止監聽所有目標元素:
observer.disconnect();
上面的 disconnect()
方法用于停止所有目標元素的監聽,并銷毀 IntersectionObserver 對象。
現在,你應該已經了解了 IntersectionObserver API。下面,我們將通過編寫一個可擴展的組件來實現效果圖演示的功能。
首先,我們定義一個 VideoProps
接口,它包含了我們的 Video
組件的屬性:
interface VideoProps { src: string; width?: number; height?: number; className?: string; }
接下來,我們定義 Video
組件,它接收 src
、width
、height
和 className
屬性:
const Video: React.FC<VideoProps> = ({ src, width = 400, height = 300, className, }) => { // ... };
在 Video
組件中,我們通過 useRef
鉤子來創建一個 videoRef
引用。我們將通過該引用來判斷視頻狀態、更新視頻真實地址、控制視頻的播放和暫停功能。
const videoRef = useRef<HTMLVideoElement>(null);
然后,我們使用 useEffect
鉤子來創建一個 IntersectionObserver
實例。我們要實現的功能主要就是通過這個實例來實現的。
useEffect(() => { const video = videoRef.current; const options = { rootMargin: "0px", threshold: 0.5, // 指定交叉比例為 50% 時觸發回調函數 }; // 創建 IntersectionObserver 實例 const observer = new IntersectionObserver(([entry]) => { // ... }, options); // 監聽 video 元素 if (video) { observer.observe(video); } // 組件卸載時取消監聽 return () => { observer.unobserve(video as Element); }; }, []);
在 IntersectionObserver
的回調函數中,我們檢查視頻是否進入視口,如果進入視口,首先要加載視頻。如果視頻加載完成,就開始播放視頻:
if (entry.isIntersecting) { // 當視頻進入視口時,開始播放視頻 if (video?.readyState === 4) { // 視頻已經加載完畢 video?.play(); } else { // 監聽視頻加載完成事件 if (video?.dataset.src) { // 將 data-src 的值賦給 src 屬性 video.src = video.dataset.src; delete video.dataset.src; video?.addEventListener("loadedmetadata", () => { video?.play(); }); } } } else { // 當視頻離開視口時,暫停視頻播放 video?.pause(); }
注意,示例代碼中使用了 video?.readyState === 4
來檢查視頻是否已經加載完畢。readyState
屬性表示視頻的加載狀態,如果它的值為 4,表示視頻已經加載完畢。
如果視頻還沒有加載完畢,我們就需要等到它加載完成后再開始播放。為了實現這一點,我們在 data-src
屬性中存儲視頻的地址,然后在視頻加載完成后再將它賦值給 src
屬性。當視頻加載完成后,記得要刪除 data-src
屬性,避免重復加載視頻:
if (video?.dataset.src) { // 將 data-src 的值賦給 src 屬性 video.src = video.dataset.src; delete video.dataset.src; video?.addEventListener("loadedmetadata", () => { video?.play(); }); }
下面是最終的代碼:
/** * @description 視頻組件 * @param {string} src 視頻地址 * @param {number} width 視頻寬度 * @param {number} height 視頻高度 * @param {string} className 自定義類名 * @returns {JSX.Element} * @example * import Video from '@/components/Video'; * <Video src="<https://www.w3schools.com/html/mov_bbb.mp4>" /> */ import React, { useRef, useEffect } from "react"; interface VideoProps { src: string; width?: number | string; height?: number | string; className?: string; } const Video: React.FC<VideoProps> = ({ src, width = 400, height = 300, className, }) => { const videoRef = useRef<HTMLVideoElement>(null); useEffect(() => { const video = videoRef.current; const options = { rootMargin: "0px", // 用于指定目標元素與根元素(視口)的邊緣間的偏移量,以便確定何時觸發回調函數。 threshold: 0.5, // 指定交叉比例為 50% 時觸發回調函數 }; // 創建 IntersectionObserver 實例 const observer = new IntersectionObserver(([entry]) => { if (entry.isIntersecting) { // 當視頻進入視口時,開始播放視頻 if (video?.readyState === 4) { // 視頻已經加載完畢 video?.play(); } else { // 監聽視頻加載完成事件 if (video?.dataset.src) { // 將 data-src 的值賦給 src 屬性 video.src = video.dataset.src; delete video.dataset.src; video?.addEventListener("loadedmetadata", () => { video?.play(); }); } } } else { // 當視頻離開視口時,暫停視頻播放 video?.pause(); } }, options); // 監聽 video 元素 if (video) { observer.observe(video); } // 組件卸載時取消監聽 return () => { observer.unobserve(video as Element); }; }, []); return ( <video loop muted controls playsInline width={width} ref={videoRef} data-src={src} // 添加 data-src 屬性 height={height} className={className} /> ); }; export default Video;
以上就是關于“怎么使用React+TS+IntersectionObserver實現視頻懶加載和自動播放功能”這篇文章的內容,相信大家都有了一定的了解,希望小編分享的內容對大家有幫助,若想了解更多相關的知識內容,請關注億速云行業資訊頻道。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。