图片懒加载

Img懒加载组件



import classnames from 'classnames'

import { useEffect, useRef, useState } from 'react'

import Icon from '../Icon'

import styles from './index.module.scss'

type Props = {

  src: string

  className?: string

  alt?: string

}

const Image = ({ className, src, alt }: Props) => {

  const imgRef = useRef<HTMLImageElement>(null)

  // 控制是否在加载

  const [loading, setLoading] = useState(true)

  // 控制是否加载失败

  const [error, setError] = useState(false)

  // 加载成功

  const onLoad = () => {

    setError(false)

    setLoading(false)

  }

  const onError = () => {

    setLoading(false)

    setError(true)

  }

  useEffect(() => {

    // 监听图片

    const observer = new IntersectionObserver(([{ isIntersecting }]) => {

      if (isIntersecting) {

        // 图片在可视区

        const current = imgRef.current!

        current.src = current.dataset.src!

        // 取消监听

        observer.unobserve(current)

      }

    })

    observer.observe(imgRef.current!)

  }, [])

  return (

    <div className={classnames(styles.root, className)}>

      {/* 加载中 */}

      {loading && (

        <div className="image-icon">

          <Icon type="iconphoto" />

        </div>

      )}

      {/* 加载出错时显示的内容 */}

      {error && (

        <div className="image-icon">

          <Icon type="iconphoto-fail" />

        </div>

      )}

      <img

        alt={alt}

        ref={imgRef}

        data-src={src}

        onLoad={onLoad}

        onError={onError}

      />

    </div>

  )

}

export default Image
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值