图片懒加载的方式

图片懒加载原理

渲染img的自定义属性data-src为真实的图片路径,判断图片是否处于可是区域内,若处于可是区域则给图片src赋值真正的图片路径data-src的值。

应用场景

懒加载的应用场景偏向于网络资源请求,解决网络资源请求过多时,造成的网站响应时间过长的问题。

如何判断图片是否在可视区域?

1.offsetTop:当前元素顶部距离父元素顶部的高度

2.window.innerHeight:可视窗口高度,不包括浏览器顶部工具栏

3.scrollTop:当前元素最顶端与窗口最顶端的距离,即超出可视区域的高度

offsetTop <= window.innerHeight + scrollTop时 元素处于可是区域内

方法一:

function App() {
  const [imgList, setImgList] = useState([])
  const [start, setStart] = useState(0)
  const [end, setEnd] = useState(10)

  useEffect(() => {
    let list:any = []
    for (let index = 0; index < 10000; index++) {
      list.push('/vite.svg')
    }
    setImgList(list)
  },[])
  
  const handleScroll = () => {
    let img = document.getElementsByTagName('img')
    const viewHeight = window.innerHeight
    const scrollTop = document.querySelector('.App')?.scrollTop
    const maxViewHeight = viewHeight + scrollTop
    let n = 11
    for (let i = n; i < img.length; i++) {
      if(img[i].offsetTop <=  maxViewHeight){
        const src = img[i].getAttribute('data-src')
        img[i].src = src || ''
      }
      n = i+1
    }
  }

  return (
    <div className="App" onScroll = {handleScroll}>
      <div className='box'>
        {imgList.map((item,index) => {
          if(index >= start && index <= end){
            return <img src={item} data-src="" className="logo" alt="Vite logo" key={index}/>
          } else {
            return <img src="" data-src={item} className="logo" alt="Vite logo" key={index}/>
          }
        })}
      </div>
    </div>
  )
}

方法二

 const handleScroll = () => {
    let img = document.getElementsByTagName('img')
    const viewHeight = document.querySelector('.App')?.clientHeight
    let n = 11
    for (let i = n; i < img.length; i++) {
      
      if(img[i].getBoundingClientRect().top <=  viewHeight){
        const src = img[i].getAttribute('data-src')
        img[i].src = src || ''
      }
      n = i+1
    }
  }

getBoundingClientRect方法:Element.getBoundingClientRect() - Web API 接口参考 | MDN

方法三

import { useState, useEffect, } from 'react'
import reactLogo from './assets/react.svg'
import './App.css'

function App() {
  const [imgList, setImgList] = useState( [])

  useEffect(() => {
    let list:any = []
    for (let index = 0; index < 10000; index++) {
      list.push('/vite.svg')
    }
    setImgList(list)
  },[])
  
  useEffect(() => {
    if(IntersectionObserver){
      imgList.length && lazyLoad()
    }
  },[imgList])

  const lazyLoad = () => {
    let img = document.getElementsByTagName('img')

    let io = new IntersectionObserver((entries) => {
      entries.forEach((entry) => {
        // 获取当前元素
        let curImg = entry.target
        console.log(entry);
        // 判断是否已经处于可视区域
        if (entry.intersectionRatio > 0 && entry.intersectionRatio <= 1) {
          curImg.setAttribute('src', curImg.getAttribute('data-src'))
        }
      })
    })

    Array.from(img).forEach((element) => {
      io.observe(element)
    })
  }

  return (
    <div className="App" onScroll = {handleScroll}>
      <div className='box'>
        {imgList.map((item,index) => {
           return <img src="" data-src={item} className="logo" alt="Vite logo" key={index}/>
        })}
      </div>
    </div>
  )
}

export default App

IntersectionObserver API 使用教程 - 阮一峰的网络日志

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值