javascript技巧

关注公众号 jb51net

关闭
首页 > 网络编程 > JavaScript > javascript技巧 > JavaScript图片懒加载

JavaScript实现图片懒加载的三种常用方法总结

作者:sevenBoy

懒加载是一种对网页性能优化的方式,也是我们经常会用到的技术,这篇文章为大家整理了JavaScript实现图片懒加载的三种常用方法,希望对大家有所帮助

1.前言

1.1 什么是使用图片懒加载

懒加载是一种对网页性能优化的方式,比如当访问一个网页的时候,优先显示可视区域的图片而不是一次加载全部的图片,当需要显示时,再发送请求加载图片。

1.2 为什么使用图片懒加载

若不使用图片懒加载,页面启动时,会加载全部的图片资源:

1.3 图片懒加载的实现原理

1 基本原理: 监听图片是否位于页面的可视区域内,若在则加载图片,不在则不加载图片

2 实现方案: 自定义属性-将图片真实地址 url 存储在自定义属性中,当监听到图片进入可视区域时,将自定义属性值赋值给 img 的 src 属性

2.实现方法

2.1 利用元素的 getBoundingClientRect 方法实现

(1)属性介绍:

利用.getBoundingClientRect实时获取物体的动态位置

(2)实现方法:

步骤 1:监听页面滚动事件,lazyLoad为页面滚动时的处理函数,在本节为处理图片懒加载。

window.addEventListener('scroll', lazyLoad)

步骤 2:判断图片是否处于可视区域内

(1)若距离顶部top小于页面的整体高度window.innerHeight

(2)若距离左侧left小于页面的整体宽度window.innerWidth

(3)同时图片的底部bottom与图片的右侧right 距页面顶部、左侧的距离均大于0

则说明该图在屏幕的可视区域内。

为了提高复用性,我们可以将它封装成一个自定义函数isVisible,将每张图片作为参数传入该函数,并返回truefalse

// 可视区域判断函数
  function isVisible(img) {
    // 判断是否在可视区域,并返回true或false
    const imgRect = img.getBoundingClientRect() // getBoundingClientRect 获取图片的动态信息
    return imgRect.bottom > 0 && imgRect.top < window.innerHeight && imgRect.right > 0 && imgRect.left < window.innerWidth
  }

步骤 3:定义图片懒加载时的处理事件,监听所有的img,判断该img是否处于可视范围内

querySelectorAll 获取的元素为伪数组 需要转为真数组,否则无法使用数组的某些方法

// 获取所有的img元素,并利用扩展运算符转为真数组
const images = [...document.querySelectorAll('img')] 

步骤 4:对每张图片进行监听,利用自定义函数isVisible判断是否在可视区域内

(1)若处于可视区域:将自定义的data-src值,赋值给真正的src属性值,其中 data-src存储图片的URL地址,并删除该元素防止重复加载

(2)若不处于可视区域:return 不做处理

// 利用循环判断每张图片是否属于可视区域
function lazyLoad(){
    for (let i = 0; i < images.length; i++) {
    // isVisible是否该图片位于可视区域 返回true 或false
      if (isVisible(images[i])) {
        // 将元素的自定义属性 data-src 赋值给元素的 src 属性
        // 等价于:img.setAttribute('src', img.getAttribute('data-src'))
        images[i].src = images[i].dataset.src 
        // 防止重复被遍历 加载完之后 删除元素不再加载
        images.splice(i, 1)
        i--
      }
    }
}
lazyLoad()

(3)整体代码:

  // html 标签结构
  <img data-src="./public/image/VCG211430870249.jpg" src="./public/image/默认.jpg" alt="">
  <img data-src="./public/image/VCG211430987515.jpg" src="./public/image/默认.jpg" alt="">
  <img data-src="./public/image/VCG211431054751.jpg" src="./public/image/默认.jpg" alt="">
  <img data-src="./public/image/VCG211435102490.jpg" src="./public/image/默认.jpg" alt="">
  <img data-src="./public/image/VCG211438229829.jpg" src="./public/image/默认.jpg" alt="">
  <img data-src="./public/image/VCG211438109615.jpg" src="./public/image/默认.jpg" alt="">
// 1 获取全部图片的DOM节点
// 注意:querySelectorAll 值为伪数组利用扩展运算符转为真数组
const images = [...document.querySelectorAll('img')] 
// 2 监听页面滚动事件
window.addEventListener('scroll', lazyLoad)
// 3 定义页面滚动的处理函数
function lazyLoad(){
    for (let i = 0; i < images.length; i++) {
    // isVisible是否该图片位于可视区域 返回true 或false
      if (isVisible(images[i])) {
        // 将元素的自定义属性 data-src 赋值给元素的 src 属性 
        // dataset.src 此为元素的自定义属性 data-src
        images[i].src = images[i].dataset.src // 等价于:img.setAttribute('src', img.getAttribute('data-src'))
        // 防止重复被遍历 加载完之后 删除元素不再加载
        images.splice(i, 1)
        i--
      }
    }
}
lazyLoad()
// 4 可视区域判断函数
  function isVisible(img) {
    // 判断是否在可视区域
    const imgRect = img.getBoundingClientRect() // getBoundingClientRect 获取图片的动态信息
    return imgRect.bottom > 0 && imgRect.top < window.innerHeight && imgRect.right > 0 && imgRect.left < window.innerWidth
  }

2.2 利用整体距离实现

(1)属性介绍:

clientHeight : 网页可见区域高

innertHeight : window 整体高度

offsetTop : 距离父级元素顶部的高度

scrollTop : 网页被卷去的距离

(2)实现方法:

可以用image.offsetTop <= document.documentElement.clientHeight + document.documentElement.scrollTop 判断图片是否可以在可视区域内。

  // html 标签结构
  <img data-src="./public/image/VCG211430870249.jpg" src="./public/image/默认.jpg" alt="">
  <img data-src="./public/image/VCG211430987515.jpg" src="./public/image/默认.jpg" alt="">
  <img data-src="./public/image/VCG211431054751.jpg" src="./public/image/默认.jpg" alt="">
  <img data-src="./public/image/VCG211435102490.jpg" src="./public/image/默认.jpg" alt="">
  <img data-src="./public/image/VCG211438229829.jpg" src="./public/image/默认.jpg" alt="">
  <img data-src="./public/image/VCG211438109615.jpg" src="./public/image/默认.jpg" alt="">
// 1 获取全部图片的DOM节点
// 注意:querySelectorAll 值为伪数组利用扩展运算符转为真数组
const images = [...document.querySelectorAll('img')] 
// 2 监听页面滚动事件
window.addEventListener('scroll', lazyLoad)
// 3 定义页面滚动的处理函数
function lazyload(e){
  // 3.1 获取屏幕的可视高度
  const clientHeight = document.documentElement.clientHeight
  // 3.2 获取屏幕的滚动距离
  const scrollTop = document.documentElement.scrollTop
  for (let i = 0; i < images.length; i++) {
    if (images[i].offsetTop < clientHeight + scrollTop) {
      images[i].setAttribute('src', images[i].getAttribute('data-src'))
    }
  }
}

2.3 利用Intersection Observer实现

Intersection Observer是一个比较新的api,他允许你追踪目标元素与其祖先元素或视窗的交叉状态,用他来检测图片是否进入视口非常方便,不用再像之前绑定事件、计算距离等。

(1)属性介绍:

(2)实现方法:

步骤 1: 监听页面滚动事件,lazyLoad为页面滚动时的处理函数,在本节为处理图片懒加载。

window.addEventListener('scroll', lazyLoad)

步骤 2: 创建图片与可视区域交叉实例

callback

 const observer = new IntersectionObserver(callback)

步骤 3: 利用observer实例上的.observe(img)方法,给每张图片绑定观察事件

// 给每一个图片绑定观察方法
  imagess.forEach(img => {
    // 图片进入视野+离开视野时会触发callback回调函数
    observer.observe(img)
  })

步骤 4: 定义图片的懒加载事件

imgArr:

  // callback 接收的参数为带有监听所有图片交叉属性的集合
  const callback = (imgArr) => {
    console.log('视图交叉时触发,离开交叉时也触发', imgArr) 
    imgArr.forEach(e => {
      // 判断是否在视野区域
      if (e.isIntersecting) {
        e.target.src = e.target.dataset.src
        // 取消监听,避免重复加载同一张图片
        observer.unobserve(e.target)
      }
    })
  }

(3)整体代码:

  // html 标签结构
  <img data-src="./public/image/VCG211430870249.jpg" src="./public/image/默认.jpg" alt="">
  <img data-src="./public/image/VCG211430987515.jpg" src="./public/image/默认.jpg" alt="">
  <img data-src="./public/image/VCG211431054751.jpg" src="./public/image/默认.jpg" alt="">
  <img data-src="./public/image/VCG211435102490.jpg" src="./public/image/默认.jpg" alt="">
  <img data-src="./public/image/VCG211438229829.jpg" src="./public/image/默认.jpg" alt="">
  <img data-src="./public/image/VCG211438109615.jpg" src="./public/image/默认.jpg" alt="">
  // intersectionObserver 交叉观察 : 目标元素和可视窗口会产生交叉区域
  const imagess = [...document.querySelectorAll('img')]
  // 2.1 创建视觉交叉的观察实例
  const observer = new IntersectionObserver(callback)
  // 2.2 给每一个图片绑定观察方法
  imagess.forEach(img => {
    // 2.3 图片进入视野+离开视野时触发 - 回调
    observer.observe(img)
  })
  // callback 接收的参数为带有监听所有图片交叉属性的集合
  const callback = (imgArr) => {
    console.log('视图交叉时触发,离开交叉时也触发', imgArr) // imgArr为
    imgArr.forEach(e => {
      // 判断是否在视野区域
      if (e.isIntersecting) {
        e.target.src = e.target.dataset.src
        // 取消观察追踪,避免重复加载同一张图片
        observer.unobserve(e.target)
      }
    })
  }

以上就是JavaScript实现图片懒加载的三种常用方法总结的详细内容,更多关于JavaScript图片懒加载的资料请关注脚本之家其它相关文章!

您可能感兴趣的文章:
阅读全文