图片懒加载(lazyload)的几种方式

背景

 

        当页面中有很多图片时,全部加载需要很多时间,而且会消耗很多渲染资源,为了解决这个问题,加强用户体验,我们先将看得到的区域中的图片加载,也就是 可视化区域 加载,剩余部分等之后再加载。

原理

        一个图片就是一个 <img> 标签,浏览器会根据 <img> 标签的 src 属性来发起请求,只要我们不给 src 赋值,或者赋值一个很小的加载图片,使用一个暂时的属性来保存图片的 src ,比如 data-src (可以用其他的名字,只要不会发送http请求就行),当图片进入可视化区域后,再把 data-src 赋值给 src 

示例

<img data-src="@/assets/imgs/test.jpg" src="@/assets/imgs/login.jpg">

1.e.offsetTop

e代表图片元素,判断图片是否进入可视区域

e.offsetTop < document.body.clientHeight + document.body.scrollTop

在这里插入图片描述

 

 data(){
    return{
      flag: true
    }
  },
  created() {
    this.throttle(this.lazyLoad, 3000)()  //首次进入加载
  },
  mounted() {
    const that = this;
    window.addEventListener('scroll',()=>{
       that.throttle(that.lazyLoad, 2000)()
    })
  },
  methods:{
    //节流优化
    throttle(fn, delay){
      const that = this;
      return function () {
        if (!that.flag) return;
        that.flag = false;  //没执行过就一直是false,会直接return
        setTimeout(() => {
          fn.apply(that, arguments);
          that.flag = true; 
          //setTimeout执行完毕后再把标记设置为true(关键)表示可以执行下一次循环。当定时器回调函数没有执行的时候标记永远是false,在开头被return掉,从而达到回流效果
        }, delay);
      }
    },
    lazyLoad(){
      let images = document.getElementsByTagName('img')  
      //加定时器的目的是为了让images能够遍历到
      setTimeout(()=>{
        for(let i =0;i<images.length;i++){
          if(images[i].offsetTop<document.body.clientHeight + document.body.scrollTop){   
            
            images[i].src = images[i].dataset.src;
          }
        }
      },300)
    }
  }

2.e.getBoundingRect

e.getBoundingClientRect() 方法返回一个 DOMRect 对象,其提供了元素的大小及其相对于视口的位置。与offsetTop方法类似,只是改变了判断图片元素是否在可视区域的计算方式。

e.getBoundingClientRect().top<document.body.clientHeight

 data(){
    return{
      flag: true
    }
  },
  created() {
    this.throttle(this.lazyLoad, 3000)()  //首次进入加载
  },
  mounted() {
    const that = this;
    window.addEventListener('scroll',()=>{
       that.throttle(that.lazyLoad, 2000)()
    })
  },
  methods:{
    //节流优化
    throttle(fn, delay){
      const that = this;
      return function () {
        if (!that.flag) return;
        that.flag = false;  //没执行过就一直是false,会直接return
        setTimeout(() => {
          fn.apply(that, arguments);
          that.flag = true; 
          //setTimeout执行完毕后再把标记设置为true(关键)表示可以执行下一次循环。当定时器回调函数没有执行的时候标记永远是false,在开头被return掉,从而达到回流效果
        }, delay);
      }
    },
    lazyLoad(){
      let images = document.getElementsByTagName('img')
      //加定时器的目的是为了让images能够遍历到
      setTimeout(()=>{
        for(let i =0;i<images.length;i++){
          if(images[i].getBoundingClientRect().top<document.body.clientHeight){   
          //getBoundingClientRect().top 元素的上边相对浏览器视窗的位置如果小于可视窗口的高度
            images[i].src = images[i].dataset.src;
          }
        }
      },300)
    }
  }

3. IntersectionObserver

交叉观察器,自动观察指定对象是否进入可视区域

let observe = new IntersectionObserver(callback, option);
created() {
    this.intersectionObserver();
},
methods:{
    intersectionObserver(){
        let images = document.getElementsByTagName('img');
        const observer = new IntersectionObserver((imgs) => {
          console.log('imgs===', imgs)
          // imgs: 目标元素集合
          imgs.forEach((img) => {
            // img.isIntersecting代表目标元素可见,可见的时候给src赋值
            if (img.isIntersecting) {
              const item = img.target
              item.src = item.dataset.src
              //解除对img元素的观察
              observer.unobserve(item);
            }
          })
       })
       //定时器和Array.from的目的是让images可遍历
       setTimeout(()=>{
        Array.from(images).forEach(item => {
          //观察img元素
          observer.observe(item);
        })
       },300)
    }
}

4.vue-lazyload库

(1)安装

npm install vue-lazyload -S

(2)全局引用并使用

import VueLazyload from 'vue-lazyload'
Vue.use(VueLazyload)

(3)使用

将 :src='xxx' 改成 vue-lazy='xxx' 

 

Lazyload 是一个常用的图片懒加载库,它支持以下几种方法: 1. 使用 HTML 属性 在 img 标签中添加 "data-src" 属性,将需要加载的图片地址作为属性值,再添加 "class" 属性,设置为 "lazyload",如下所示: ```html <img class="lazyload" data-src="image.png" alt="Image"> ``` 2. 使用 JavaScript 先将需要懒加载的图片地址存储在一个数组中,再使用 JavaScript 获取所有需要懒加载的图片元素,将它们的 "src" 属性设置为一个占位符(如空白图片),再将 "data-src" 属性的值设置为需要加载的图片地址。 最后,在 window 对象的 "load" 和 "scroll" 事件中,判断图片是否进入可视区域,如果是,则将 "data-src" 属性的值赋给 "src" 属性,实现图片加载。 ```javascript // 存储需要懒加载的图片地址 const images = [ 'image1.png', 'image2.png', 'image3.png' ]; // 获取所有需要懒加载的图片元素 const lazyImages = document.querySelectorAll('.lazyload'); // 遍历所有图片元素,设置 src 属性为占位符,data-src 属性为需要加载的图片地址 lazyImages.forEach((lazyImage, index) => { lazyImage.src = 'placeholder.png'; lazyImage.dataset.src = images[index]; }); // 判断图片是否进入可视区域,如果是,则将 data-src 属性的值赋给 src 属性 function lazyLoad() { lazyImages.forEach(lazyImage => { const imageTop = lazyImage.getBoundingClientRect().top; if (imageTop < window.innerHeight) { lazyImage.src = lazyImage.dataset.src; lazyImage.classList.remove('lazyload'); } }); } // 监听 window 对象的 load 和 scroll 事件,执行懒加载 window.addEventListener('load', lazyLoad); window.addEventListener('scroll', lazyLoad); ``` 3. 使用 IntersectionObserver API IntersectionObserver 是一个 Web API,它可以监测元素是否进入可视区域,可以用于图片懒加载。 首先,创建一个 IntersectionObserver 实例,设置回调函数,当被观察的元素进入可视区域时,会执行回调函数。在回调函数中,将 "data-src" 属性的值赋给 "src" 属性,实现图片加载。 ```javascript // 创建 IntersectionObserver 实例 const observer = new IntersectionObserver((entries, observer) => { entries.forEach(entry => { if (entry.isIntersecting) { const lazyImage = entry.target; lazyImage.src = lazyImage.dataset.src; lazyImage.classList.remove('lazyload'); observer.unobserve(lazyImage); } }); }); // 获取所有需要懒加载的图片元素 const lazyImages = document.querySelectorAll('.lazyload'); // 遍历所有图片元素,将其添加到 IntersectionObserver 实例中进行观察 lazyImages.forEach(lazyImage => { observer.observe(lazyImage); }); ```
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值