1

父组件

import React from 'react'
import ImgList from './imgList'
class LazyLoadImg extends React.Component {
    constructor() {
        super()
    }

    getImg = ()=>[ //模拟获取图片信息
        { src: 'http://localhost:8080/imgs/chaomifen.jpg', title: '1' },
        { src: 'http://localhost:8080/imgs/dapanji.jpg', title: '2' },
        { src: 'http://localhost:8080/imgs/hulayangti.jpg', title: '3' },
        { src: 'http://localhost:8080/imgs/jiaomaji.jpg', title: '4' },
        { src: 'http://localhost:8080/imgs/kaoyu.jpg', title: '5' },
        { src: 'http://localhost:8080/imgs/laziji.jpg', title: '6' },
    ]

    render() {
        return (
            <>
                <ImgList imgArray={this.getImg()}/>
            </>
        )
    }
}

子组件

import React from 'react'
class ImgList extends React.Component {
    constructor() {
        super()
        this.imgRefs = []
    }
    renderImgList = () =>{
            return <>
               {
                    this.props.imgArray.map((item, index) => {
                        const imgref = React.createRef()
                        this.imgRefs.push(imgref)
                        return <div key={index} style={{width:'500px',height:'500px'}}>
                            <img ref={imgref} src='' data-src={item.src} title={item.title} />
                        </div>
                    })
               }
               <img src='' onError={this.onload}/>
                </>
            
        }
    imgObserver = new IntersectionObserver(
        entries => {
            entries.forEach(item => {
              // entries 是被监听的元素集合它是一个数组
              if (item.intersectionRatio <= 0) return // intersectionRatio 是可见度 如果当前元素不可见就结束该函数。
              const {target} = item
              target.src = target.dataset.src // 将 h5 自定义属性赋值给 src (进入可见区则加载图片)
              this.imgObserver.unobserve(item.target) //加载过的不用加载了
            })
          },
          {
            threshold: [0.01]
          }
    )
    onload = () => {
        this.imgRefs.forEach(item => {
          this.imgObserver.observe(item.current) // 添加需要被观察的元素。
        })
      }
    render() {
        return (
            <>
                {this.renderImgList()}
            </>
        )
    }
}
export default ImgList

在子组件里也可以在componentDidUpdate调用onload方法
renderImgList此方法中使用<img src='' onError={this.onload}/>是为了在上面的图片都加载完后,再调用onload方法
本文中的图片是在本地的tomcat中。

首次打开

此次可以看到只加载了两张图片
image.png

滚动条滚动

此次可以看到又加载了两张图片
image.png

注意

1.加载过的要设置不用加载,不然即使加载过,再次出现在可视范围内还会再加载
2.如果涉及到分页,用<img src='' onError={this.onload}/> 可能会在第二页不会执行onload方法,这是可以考虑用componentDidUpdate来实现

    componentDidUpdate(prevProps, prevState) {
        if(!isEqual(this.props.imgArray,prevProps.imgArray)){
            this.onload()
        }
    }

利用 componentDidUpdate 实现添加被观察的元素

父组件

import React from 'react'
import ImgList from './imgList'
class LazyLoadImg extends React.Component {
    constructor() {
        super()
        this.state={
            imgArray:[]
        }
    }
    componentDidMount(){
        this.setState({
            imgArray:this.getImg()
        })
    }
    getImg = ()=>[
        { src: 'http://localhost:8080/imgs/chaomifen.jpg', title: '1' },
        { src: 'http://localhost:8080/imgs/dapanji.jpg', title: '2' },
        { src: 'http://localhost:8080/imgs/hulayangti.jpg', title: '3' },
        { src: 'http://localhost:8080/imgs/jiaomaji.jpg', title: '4' },
        { src: 'http://localhost:8080/imgs/kaoyu.jpg', title: '5' },
        { src: 'http://localhost:8080/imgs/laziji.jpg', title: '6' },
    ]

    render() {
        return (
            <>
                <ImgList imgArray={this.state.imgArray}/>
            </>
        )
    }
}
export default LazyLoadImg

子组件

import React from 'react'
import isEqual from 'lodash/isEqual'

class ImgList extends React.Component {
    constructor() {
        super()
        this.imgRefs = []
    }

    
    componentDidUpdate(prevProps, prevState) {
        if(!isEqual(this.props.imgArray,prevProps.imgArray)){
            this.onload()
        }
    }
    

    renderImgList = () =>{
            return <>
               {
                    this.props.imgArray.map((item, index) => {
                        const imgref = React.createRef()
                        this.imgRefs.push(imgref)
                        return <div key={index} style={{width:'500px',height:'500px'}}>
                            <img ref={imgref} src='' data-src={item.src} title={item.title} />
                        </div>
                    })
               }
               {/* <img src='' onError={this.onload}/> */}
                </>
            
        }

    imgObserver = new IntersectionObserver(
        entries => {
            entries.forEach(item => {
              // entries 是被监听的元素集合它是一个数组
              if (item.intersectionRatio <= 0) return // intersectionRatio 是可见度 如果当前元素不可见就结束该函数。
              const {target} = item
              target.src = target.dataset.src // 将 h5 自定义属性赋值给 src (进入可见区则加载图片)
              this.imgObserver.unobserve(item.target) //加载过的不用加载了
            })
          },
          {
            threshold: [0.01]
          }
    )
    onload = () => {
        this.imgRefs.forEach(item => {
          this.imgObserver.observe(item.current) // 添加需要被观察的元素。
        })
      }
    
    render() {
        return (
            <>
                {this.renderImgList()}
            </>
        )
    }
}
export default ImgList

意思就是这么个意思,当图片出现在可视范围内,再把真正的图片地址给src


我滴个神呐
12 声望1 粉丝