最近在做即时消息,消息类型除了文字还有音频、视频、图片展示,如果消息很多,在切换聊天框时,会有明显卡顿,后续做了懒加载,方案是只加载用户能看到的资源,看不到的先不加载;
LazyAudio.tsx
import {useRef, useEffect} from 'react';interface PropsType {url: string,className?: string,
}export default function LazyAudio({url, className= ''}: PropsType) {const currentRef: any = useRef(null)useEffect(() => {if (!currentRef.current) {return;}const observer = new IntersectionObserver(([{ isIntersecting }]) => {// 表示进入了可视范围if (isIntersecting) {if (!currentRef.current.src) {currentRef.current.src = url;observer.unobserve(currentRef.current);}}});observer.observe(currentRef.current);return () => {if (currentRef.current) {observer.unobserve(currentRef.current);}}}, [])return (<><audioref={currentRef}controls preload="metadata" className={`${className} `}></audio></>)
}
LazyImg.tsx
import {useEffect, useRef} from 'react';interface PropsType {url: string,className?: string,onClick: () => void,
}
export default function LazyImg({url, className = '', onClick}: PropsType) {const currentRef: any = useRef(null)// 图片加载完成后const imageLoaded = () => {// 图片加载完成后重置了高度currentRef.current.style.height = 'auto';}useEffect(() => {if (!currentRef.current) {return;}const observer = new IntersectionObserver(([{ isIntersecting }]) => {// 表示进入了可视范围if (isIntersecting) {if (!currentRef.current.src) {currentRef.current.src = url;observer.unobserve(currentRef.current);}}});observer.observe(currentRef.current);return () => {if (currentRef.current) {observer.unobserve(currentRef.current);}}}, [])return <><img alt="无法加载图片"width={320}height={320}ref={currentRef}onClick={onClick}onLoad={imageLoaded}className={`${className} `}/></>
}
LazyVideo.tsx
import {useEffect, useRef} from 'react';interface PropsType {url: string,className?: string,width?: number,height?: number,
}
export default function LazyVideo({url, className = '', width = 320, height = 240}: PropsType) {const currentRef: any = useRef(null)useEffect(() => {if (!currentRef.current) {return;}const observer = new IntersectionObserver(([{ isIntersecting }]) => {// 表示进入了可视范围if (isIntersecting) {if (!currentRef.current.src) {currentRef.current.src = url;observer.unobserve(currentRef.current);}}});observer.observe(currentRef.current);return () => {if (currentRef.current) {observer.unobserve(currentRef.current);}}}, [])return (<><video ref={currentRef}width={width}height={height}controls preload="metadata"className={`${className} `}></video></>)
}