IntersectionObserver无限下拉

335 阅读1分钟
import 'intersection-observer';

 const loadMoreRef = useRef<HTMLDivElement>(null);
 const [listCollect, setListCollect] = useState(sourceListCollect);
 useEffect(() => {
     const loadMoreObj = loadMoreRef.current;
     const intersectionObserver = new IntersectionObserver(
         (entries) => {
             const loadingEntry = entries[0];
             if (loadingEntry.isIntersecting) {
                 // 请求数据并插入列表
                 setListCollect(
                     listCollect.concat(
                         mainData.floorList[0].renderData.data.skuCollect,
                     ),
                 );
             }
         },
         {
             rootMargin: '0px 0px 600px 0px', // 提前加载高度
         },
     );

     loadMoreObj && intersectionObserver.observe(loadMoreObj); // 观察尾部元素

     return () => {
         loadMoreObj && intersectionObserver.unobserve(loadMoreObj);
     };
 }, 
 
 
 return (
<div>
     <div ref={loadMoreRef}>111</div>
 </div>
);

图片懒加载

/**
 * 图片懒加载
 * loadingImg loading图片
 * src 图片地址
 * errorImg 错误图片地址
 */
import React, {
    FunctionComponent,
    ReactElement,
    useRef,
    useEffect,
    useState,
} from 'react';
import _LoadingImg from './loading';
import { CSSProperties, ImgHTMLAttributes } from 'react';
import 'intersection-observer';
export interface LazyLoadPropsType {
    loadingImg?: string;
    src: string;
    errorImg?: string;
    alt?: string;
    style?: CSSProperties;
    imgOptions?: Omit<ImgHTMLAttributes<HTMLImageElement>, 'src'>;
    className?: string | undefined;
    aspectRatio?: number;
}

const Image: FunctionComponent<LazyLoadPropsType> = ({
    src,
    loadingImg,
    errorImg,
    style,
    imgOptions = {},
    className,
    alt = '',
    aspectRatio,
}): ReactElement => {
    const imgRef = useRef<HTMLImageElement>(null);
    const [imgURL, setImgURL] = useState(_LoadingImg || loadingImg);

    useEffect(() => {
        const imgObj = imgRef.current;
        const intersectionObserver = new IntersectionObserver(
            (entries) => {
                entries.forEach((item) => {
                    if (item.isIntersecting) {
                        setImgURL(src);
                        if (imgObj) {
                            imgObj.onload = () => {
                                intersectionObserver.unobserve(item.target);
                            };

                            imgObj.onerror = () => {
                                setImgURL(errorImg || '');
                            };
                        }
                    }
                });
            },
            { rootMargin: '-10px', threshold: 0 },
        );

        imgObj && intersectionObserver.observe(imgObj);

        return () => {
            imgObj && intersectionObserver.unobserve(imgObj);
        };
    }, [errorImg, src]);

    if (aspectRatio) {
        style = { ...style, height: 1190 / aspectRatio };
    }
    return (
        <img
            className={className}
            src={imgURL}
            alt={alt}
            {...imgOptions}
            ref={imgRef}
            style={{ width: '100%', height: '100%', ...style }}
        />
    );
};

export default Image;