一文教你學(xué)會(huì)用JS實(shí)現(xiàn)圖片懶加載功能
通過IntersectionObserver實(shí)現(xiàn)圖片懶加載功能
首先來介紹一下IntersectionObserver,這個(gè)在MDN中有十分詳細(xì)的介紹.可以直接去看原文.這里簡單介紹一下他的用法.
IntersectionObserver
IntersectionObserver 是一個(gè) JavaScript 的 API,用于觀察目標(biāo)元素與其祖先元素或視窗(viewport)之間的交叉狀態(tài)。它能夠提供一種高效的方式來檢測目標(biāo)元素是否進(jìn)入或離開視窗,或者與其父元素發(fā)生交叉,從而實(shí)現(xiàn)懶加載、無限滾動(dòng)、動(dòng)態(tài)加載等功能。IntersectionObserver API 在現(xiàn)代瀏覽器中得到廣泛支持。
屬性:
IntersectionObserver.root:表示根元素(root)的可見區(qū)域。它是一個(gè) Document 對象的引用。默認(rèn)情況下,根元素為視窗(viewport)。你可以指定一個(gè)特定的元素,使其成為觀察器的根元素。如果未指定,則默認(rèn)為視窗。IntersectionObserver.rootMargin:用于擴(kuò)展或縮小根元素的可見區(qū)域。它是一個(gè)字符串,類似于 CSS 的margin屬性,可以包含像素值或百分比值。例如,"10px 20px 30px 40px" 或者 "5% 10%"。這個(gè)屬性用于擴(kuò)大或縮小根元素的可見區(qū)域,使得在進(jìn)入或離開視窗之前,目標(biāo)元素需要提前或推遲一定的距離。IntersectionObserver.thresholds:一個(gè)數(shù)組,表示觸發(fā) IntersectionObserver 回調(diào)的交叉閾值。交叉閾值是一個(gè)介于 0 和 1 之間的值,表示目標(biāo)元素可見區(qū)域與根元素可見區(qū)域相交的百分比。當(dāng)目標(biāo)元素的可見區(qū)域與根元素的可見區(qū)域相交達(dá)到或超過閾值時(shí),會(huì)觸發(fā)回調(diào)函數(shù)。默認(rèn)情況下,閾值為 [0],表示目標(biāo)元素有任何部分進(jìn)入可見區(qū)域時(shí)都會(huì)觸發(fā)回調(diào)。你可以自定義多個(gè)閾值,以實(shí)現(xiàn)更精確的觸發(fā)條件。
方法:
IntersectionObserver.observe(target: Element):將一個(gè)目標(biāo)元素添加到 IntersectionObserver 中進(jìn)行觀察。當(dāng)目標(biāo)元素的交叉狀態(tài)滿足設(shè)定的條件時(shí),會(huì)觸發(fā) IntersectionObserver 的回調(diào)函數(shù)。IntersectionObserver.unobserve(target: Element):停止對指定目標(biāo)元素的觀察,即使目標(biāo)元素的交叉狀態(tài)滿足條件,也不會(huì)觸發(fā) IntersectionObserver 的回調(diào)函數(shù)。IntersectionObserver.disconnect():停止對所有目標(biāo)元素的觀察,調(diào)用該方法后,即使目標(biāo)元素的交叉狀態(tài)發(fā)生變化,也不會(huì)觸發(fā) IntersectionObserver 的回調(diào)函數(shù)。IntersectionObserver.takeRecords():返回一個(gè)包含所有觀察目標(biāo)元素的 IntersectionObserverEntry 對象數(shù)組。每個(gè) IntersectionObserverEntry 對象包含目標(biāo)元素的交叉狀態(tài)信息,如可見區(qū)域的大小和位置等。
簡單實(shí)現(xiàn)
圖片獲取:
// globEager是靜態(tài)加載模式
// glob是懶加載模式
// let imgList=import.meta.glob('./assets/*.*',{eager:true}) ----便是靜態(tài)加載模式
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);在很多時(shí)候,獲取圖片列表的方式都是將圖片路徑添加到一個(gè)數(shù)組中,進(jìn)行獲取,十分繁瑣,而上面的這種方式相對而言要簡單很多.import.meta.glob和import.meta.globEager兩種方式大同小異,但是import.meta.glob這種可以直接實(shí)現(xiàn)圖片懶加載引入,而后面那種則是通過靜態(tài)資源的方式將圖片進(jìn)行引入.這便是這兩種方式的區(qū)別.由于在這個(gè)dome中要實(shí)現(xiàn)圖片懶加載,所以是使用的是第二種方式引入(在第一種方式加一個(gè){eager:true}便可以達(dá)到第二種引入方式的效果).
先來看看imgList的輸出結(jié)果:

可以很明顯的看到default就是圖片的路徑,那么只需要將其獲取即可
let arr=Object.values(imgList).map((item:any)=>item.default)
因?yàn)榉祷氐氖且粋€(gè)對象,所以便可以使用Object.values來獲取到value,再通過map遍歷的方式獲取到其default值

從而便獲得了其路徑,這種獲取路徑的方式還是比較輕松,且方便的.
再解決完圖片問題之后,便是懶加載部分的實(shí)現(xiàn)了.
懶加載實(shí)現(xiàn):
關(guān)于IntersectionObserver的屬性和方法在前面也簡單的介紹了.同時(shí)也附上了MDN相關(guān)鏈接.這里便不會(huì)再去贅述了.
相關(guān)代碼展示:
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)
}在對于前面屬性和方法的了解的加持下,看這段代碼屬實(shí)不難.其中定時(shí)器只是為了更好的去呈現(xiàn)懶加載的這個(gè)過程.
上述代碼中,通過使用vue的矢量圖來作為默認(rèn)圖片,當(dāng)未加載時(shí),展示這張圖.看函數(shù)主體:
enr所返回的就是每一個(gè)圖片所返回的IntersectionObserver

因?yàn)橹惶砑恿巳龔垐D片所以返回了三個(gè)對象,而所需要關(guān)注的就是intersectionRatio這個(gè)屬性,當(dāng)它大于0時(shí),便會(huì)將圖片路徑更換為指定路徑,從而實(shí)現(xiàn)了圖片懶加載,當(dāng)然在實(shí)現(xiàn)這一功能之后,也要關(guān)閉 observer.unobserve(el),不然會(huì)一直關(guān)注這一個(gè).
整體代碼呈現(xiàn):
<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是靜態(tài)加載模式
// glob是懶加載模式
// let imgList=import.meta.glob('./assets/*.*',{eager:true}) ----便是靜態(tài)加載模式
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>到此這篇關(guān)于一文教你學(xué)會(huì)用JS實(shí)現(xiàn)圖片懶加載功能的文章就介紹到這了,更多相關(guān)JS實(shí)現(xiàn)圖片懶加載功能內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
JS實(shí)現(xiàn)仿Windows7風(fēng)格的網(wǎng)頁右鍵菜單效果代碼
這篇文章主要介紹了JS實(shí)現(xiàn)仿Windows7風(fēng)格的網(wǎng)頁右鍵菜單效果代碼,涉及JavaScript鼠標(biāo)右鍵響應(yīng)及動(dòng)態(tài)生成頁面菜單的技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下2015-09-09
uniapp通過概率實(shí)現(xiàn)隨機(jī)抽獎(jiǎng)的項(xiàng)目實(shí)踐
在很多電商平臺(tái)或者活動(dòng)中,都會(huì)有類似抽獎(jiǎng)贏優(yōu)惠券的功能,本文主要介紹了uniapp通過概率實(shí)現(xiàn)隨機(jī)抽獎(jiǎng)的項(xiàng)目實(shí)踐,具有一定的參考價(jià)值,感興趣的可以了解一下2025-04-04
一些Javascript的IE和Firefox(火狐)兼容性的問題總結(jié)及常用例子
下面是一些Javascript的IE和Firefox(火狐)兼容性的常用例子2009-05-05
Javascript中的return作用及javascript return關(guān)鍵字用法詳解
本文給大家介紹Javascript中的return作用及javascript return關(guān)鍵字用法詳解,對于大家學(xué)習(xí)javascript中的return知識(shí)有所幫助,感興趣的朋友一起學(xué)習(xí)吧2015-11-11
一文帶你搞懂JavaScript中轉(zhuǎn)義字符的使用
說起轉(zhuǎn)義字符,大家最先想到的肯定是使用反斜杠,這也是我們最常見的,很多編程語言都支持。除了反斜杠以外,在前端開發(fā)中,還有其他幾種轉(zhuǎn)義字符,也是較常見的,本文將對這些做一個(gè)總結(jié)2023-02-02
JS實(shí)現(xiàn)簡單可拖動(dòng)的模態(tài)框
這篇文章主要為大家詳細(xì)介紹了JS實(shí)現(xiàn)簡單可拖動(dòng)的模態(tài)框,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-07-07

