通过IntersectionObserver实现图片懒加载功能

图片懒加载是日常开发会经常使用的一个功能,但是在日常中可能使用v-lazy便直接实现了图片懒加载,现在想通过原生js来实现一下图片懒加载的功能.

首先来介绍一下IntersectionObserver,这个在MDN中有十分详细的介绍.可以直接去看原文.这里简单介绍一下他的用法.

IntersectionObserver

IntersectionObserver 是一个 JavaScript 的 API,用于观察目标元素与其祖先元素或视窗(viewport)之间的交叉状态。它能够提供一种高效的方式来检测目标元素是否进入或离开视窗,或者与其父元素发生交叉,从而实现懒加载、无限滚动、动态加载等功能。IntersectionObserver API 在现代浏览器中得到广泛支持。

属性:

  1. IntersectionObserver.root:表示根元素(root)的可见区域。它是一个 Document 对象的引用。默认情况下,根元素为视窗(viewport)。你可以指定一个特定的元素,使其成为观察器的根元素。如果未指定,则默认为视窗。

  2. IntersectionObserver.rootMargin:用于扩展或缩小根元素的可见区域。它是一个字符串,类似于 CSS 的 margin 属性,可以包含像素值或百分比值。例如,"10px 20px 30px 40px" 或者 "5% 10%"。这个属性用于扩大或缩小根元素的可见区域,使得在进入或离开视窗之前,目标元素需要提前或推迟一定的距离。

  3. IntersectionObserver.thresholds:一个数组,表示触发 IntersectionObserver 回调的交叉阈值。交叉阈值是一个介于 0 和 1 之间的值,表示目标元素可见区域与根元素可见区域相交的百分比。当目标元素的可见区域与根元素的可见区域相交达到或超过阈值时,会触发回调函数。默认情况下,阈值为 [0],表示目标元素有任何部分进入可见区域时都会触发回调。你可以自定义多个阈值,以实现更精确的触发条件。

方法:

  1. IntersectionObserver.observe(target: Element):将一个目标元素添加到 IntersectionObserver 中进行观察。当目标元素的交叉状态满足设定的条件时,会触发 IntersectionObserver 的回调函数。

  2. IntersectionObserver.unobserve(target: Element):停止对指定目标元素的观察,即使目标元素的交叉状态满足条件,也不会触发 IntersectionObserver 的回调函数。

  3. IntersectionObserver.disconnect():停止对所有目标元素的观察,调用该方法后,即使目标元素的交叉状态发生变化,也不会触发 IntersectionObserver 的回调函数。

  4. IntersectionObserver.takeRecords():返回一个包含所有观察目标元素的 IntersectionObserverEntry 对象数组。每个 IntersectionObserverEntry 对象包含目标元素的交叉状态信息,如可见区域的大小和位置等。

简单实现

图片获取:

// globEager是静态加载模式
// glob是懒加载模式
// let imgList=import.meta.glob('./assets/*.*',{eager:true}) ----便是静态加载模式
let imgList:Record<string,{default:string}>=import.meta.glob('./assets/*.*',{eager:true})
let arr=Object.values(imgList).map((item:any)=>item.default)
console.log(arr);

在很多时候,获取图片列表的方式都是将图片路径添加到一个数组中,进行获取,十分繁琐,而上面的这种方式相对而言要简单很多.import.meta.globimport.meta.globEager两种方式大同小异,但是import.meta.glob这种可以直接实现图片懒加载引入,而后面那种则是通过静态资源的方式将图片进行引入.这便是这两种方式的区别.由于在这个dome中要实现图片懒加载,所以是使用的是第二种方式引入(在第一种方式加一个{eager:true}便可以达到第二种引入方式的效果).

先来看看imgList的输出结果:

 

可以很明显的看到default就是图片的路径,那么只需要将其获取即可

let arr=Object.values(imgList).map((item:any)=>item.default)

因为返回的是一个对象,所以便可以使用Object.values来获取到value,再通过map遍历的方式获取到其default

 

从而便获得了其路径,这种获取路径的方式还是比较轻松,且方便的.

再解决完图片问题之后,便是懒加载部分的实现了.

懒加载实现:

关于IntersectionObserver的属性和方法在前面也简单的介绍了.同时也附上了MDN相关链接.这里便不会再去赘述了.

相关代码展示:

let vLazy:Directive<HTMLImageElement,string>=async (el,binging)=>{
  const def=await import('./assets/vue.svg')
  el.src=def.default
  console.log(el);
  const observer=new IntersectionObserver(enr=>{
    console.log(enr[0]);
    if(enr[0].intersectionRatio>0){
      setTimeout(()=>{
        el.src=binging.value
      },2000)
      observer.unobserve(el)
    }
    
  })
  observer.observe(el)
  
}

在对于前面属性和方法的了解的加持下,看这段代码属实不难.其中定时器只是为了更好的去呈现懒加载的这个过程.

上述代码中,通过使用vue的矢量图来作为默认图片,当未加载时,展示这张图.看函数主体:

enr所返回的就是每一个图片所返回的IntersectionObserver

因为只添加了三张图片所以返回了三个对象,而所需要关注的就是intersectionRatio这个属性,当它大于0时,便会将图片路径更换为指定路径,从而实现了图片懒加载,当然在实现这一功能之后,也要关闭observer.unobserve(el),不然会一直关注这一个.

 

整体代码呈现:

<template>
<div >
  <div class="card">
    <img v-lazy="item" v-for="(item,index) in arr" :src="item" :key="index" alt="" width="360" height="500" >
  </div>
</div>
</template>
​
<script setup lang='ts'>
import HelloWorld from './components/HelloWorld.vue';
import type {Directive } from 'vue'
// globEager是静态加载模式
// glob是懒加载模式
// let imgList=import.meta.glob('./assets/*.*',{eager:true}) ----便是静态加载模式
let imgList:Record<string,{default:string}>=import.meta.glob('./assets/*.*',{eager:true})
let arr=Object.values(imgList).map((item:any)=>item.default)
console.log(arr);
let vLazy:Directive<HTMLImageElement,string>=async (el,binging)=>{
  const def=await import('./assets/vue.svg')
  el.src=def.default
  console.log(el);
  const observer=new IntersectionObserver(enr=>{
    console.log(enr[0]);
    if(enr[0].intersectionRatio>0){
      setTimeout(()=>{
        el.src=binging.value
      },2000)
      observer.unobserve(el)
    }
    
  })
  observer.observe(el)
  
}
</script>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
IntersectionObserver是一种新的API,可以用于实现懒加载。懒加载是指在页面滚动时,只加载可视区域内的内容,而不是一次性加载所有内容。这样可以优化网页加载速度,提升用户体验。 下面是IntersectionObserver实现懒加载的步骤: 1. 创建一个IntersectionObserver对象:可以通过其构造函数创建。 2. 选取需要进行懒加载的图片或其他DOM元素,将其包裹在一个容器元素中。 3. 使用IntersectionObserver对象的observe方法来观察容器元素。 4. 在回调函数中获取到可见性变化的元素,如果元素进入可视区域,就将其src属性指向真实图片的地址,实现图片的懒加载。 下面是一个示例代码: ``` let lazyImages = document.querySelectorAll('.lazy-image'); let options = { root: null, // 窗口视图作为根元素 rootMargin: '0px', // 不添加边框 threshold: 0.1 // 当可见性达到10%时触发回调 }; let observer = new IntersectionObserver(function(entries, observer) { entries.forEach(entry => { if (entry.isIntersecting) { // 元素进入可见视图 let lazyImage = entry.target; lazyImage.src = lazyImage.dataset.src; observer.unobserve(lazyImage); // 取消观察 } }); }, options); lazyImages.forEach(lazyImage => { observer.observe(lazyImage); }); ``` 在上面的代码中,我们首先选取了所有带有lazy-image类的图片元素,然后创建了一个IntersectionObserver对象,指定了观察的根元素和触发回调的阈值。接着,我们遍历了所有图片元素,使用observe方法观察了每个元素。在回调函数中,我们判断元素是否进入了可视区域,如果是,就将该元素的data-src属性值赋给src属性,实现懒加载,然后取消对该元素的观察。最后,我们通过forEach方法将所有图片元素添加到IntersectionObserver的观察列表中。 注意,容器元素的宽高需要在CSS中指定,否则IntersectionObserver无法准确计算元素的可见性。同样,图片元素的真实地址需要通过data-src属性指定,而不是src属性。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值