一文教你学会用JS实现图片懒加载功能
作者:chenxuyan
通过IntersectionObserver实现图片懒加载功能
首先来介绍一下IntersectionObserver
,这个在MDN中有十分详细的介绍.可以直接去看原文.这里简单介绍一下他的用法.
IntersectionObserver
IntersectionObserver 是一个 JavaScript 的 API,用于观察目标元素与其祖先元素或视窗(viewport)之间的交叉状态。它能够提供一种高效的方式来检测目标元素是否进入或离开视窗,或者与其父元素发生交叉,从而实现懒加载、无限滚动、动态加载等功能。IntersectionObserver API 在现代浏览器中得到广泛支持。
属性:
IntersectionObserver.root
:表示根元素(root)的可见区域。它是一个 Document 对象的引用。默认情况下,根元素为视窗(viewport)。你可以指定一个特定的元素,使其成为观察器的根元素。如果未指定,则默认为视窗。IntersectionObserver.rootMargin
:用于扩展或缩小根元素的可见区域。它是一个字符串,类似于 CSS 的margin
属性,可以包含像素值或百分比值。例如,"10px 20px 30px 40px" 或者 "5% 10%"。这个属性用于扩大或缩小根元素的可见区域,使得在进入或离开视窗之前,目标元素需要提前或推迟一定的距离。IntersectionObserver.thresholds
:一个数组,表示触发 IntersectionObserver 回调的交叉阈值。交叉阈值是一个介于 0 和 1 之间的值,表示目标元素可见区域与根元素可见区域相交的百分比。当目标元素的可见区域与根元素的可见区域相交达到或超过阈值时,会触发回调函数。默认情况下,阈值为 [0],表示目标元素有任何部分进入可见区域时都会触发回调。你可以自定义多个阈值,以实现更精确的触发条件。
方法:
IntersectionObserver.observe(target: Element)
:将一个目标元素添加到 IntersectionObserver 中进行观察。当目标元素的交叉状态满足设定的条件时,会触发 IntersectionObserver 的回调函数。IntersectionObserver.unobserve(target: Element)
:停止对指定目标元素的观察,即使目标元素的交叉状态满足条件,也不会触发 IntersectionObserver 的回调函数。IntersectionObserver.disconnect()
:停止对所有目标元素的观察,调用该方法后,即使目标元素的交叉状态发生变化,也不会触发 IntersectionObserver 的回调函数。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.glob
和import.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>
到此这篇关于一文教你学会用JS实现图片懒加载功能的文章就介绍到这了,更多相关JS实现图片懒加载功能内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!