一文教你學(xué)會(huì)用JS實(shí)現(xiàn)圖片懶加載功能
通過(guò)IntersectionObserver實(shí)現(xiàn)圖片懶加載功能
首先來(lái)介紹一下IntersectionObserver
,這個(gè)在MDN中有十分詳細(xì)的介紹.可以直接去看原文.這里簡(jiǎn)單介紹一下他的用法.
IntersectionObserver
IntersectionObserver 是一個(gè) JavaScript 的 API,用于觀察目標(biāo)元素與其祖先元素或視窗(viewport)之間的交叉狀態(tài)。它能夠提供一種高效的方式來(lái)檢測(cè)目標(biāo)元素是否進(jìn)入或離開(kāi)視窗,或者與其父元素發(fā)生交叉,從而實(shí)現(xiàn)懶加載、無(wú)限滾動(dòng)、動(dòng)態(tài)加載等功能。IntersectionObserver API 在現(xiàn)代瀏覽器中得到廣泛支持。
屬性:
IntersectionObserver.root
:表示根元素(root)的可見(jiàn)區(qū)域。它是一個(gè) Document 對(duì)象的引用。默認(rèn)情況下,根元素為視窗(viewport)。你可以指定一個(gè)特定的元素,使其成為觀察器的根元素。如果未指定,則默認(rèn)為視窗。IntersectionObserver.rootMargin
:用于擴(kuò)展或縮小根元素的可見(jiàn)區(qū)域。它是一個(gè)字符串,類(lèi)似于 CSS 的margin
屬性,可以包含像素值或百分比值。例如,"10px 20px 30px 40px" 或者 "5% 10%"。這個(gè)屬性用于擴(kuò)大或縮小根元素的可見(jiàn)區(qū)域,使得在進(jìn)入或離開(kāi)視窗之前,目標(biāo)元素需要提前或推遲一定的距離。IntersectionObserver.thresholds
:一個(gè)數(shù)組,表示觸發(fā) IntersectionObserver 回調(diào)的交叉閾值。交叉閾值是一個(gè)介于 0 和 1 之間的值,表示目標(biāo)元素可見(jiàn)區(qū)域與根元素可見(jiàn)區(qū)域相交的百分比。當(dāng)目標(biāo)元素的可見(jiàn)區(qū)域與根元素的可見(jiàn)區(qū)域相交達(dá)到或超過(guò)閾值時(shí),會(huì)觸發(fā)回調(diào)函數(shù)。默認(rèn)情況下,閾值為 [0],表示目標(biāo)元素有任何部分進(jìn)入可見(jià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)
:停止對(duì)指定目標(biāo)元素的觀察,即使目標(biāo)元素的交叉狀態(tài)滿足條件,也不會(huì)觸發(fā) IntersectionObserver 的回調(diào)函數(shù)。IntersectionObserver.disconnect()
:停止對(duì)所有目標(biāo)元素的觀察,調(diào)用該方法后,即使目標(biāo)元素的交叉狀態(tài)發(fā)生變化,也不會(huì)觸發(fā) IntersectionObserver 的回調(diào)函數(shù)。IntersectionObserver.takeRecords()
:返回一個(gè)包含所有觀察目標(biāo)元素的 IntersectionObserverEntry 對(duì)象數(shù)組。每個(gè) IntersectionObserverEntry 對(duì)象包含目標(biāo)元素的交叉狀態(tài)信息,如可見(jiàn)區(qū)域的大小和位置等。
簡(jiǎn)單實(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)行獲取,十分繁瑣,而上面的這種方式相對(duì)而言要簡(jiǎn)單很多.import.meta.glob
和import.meta.globEager
兩種方式大同小異,但是import.meta.glob
這種可以直接實(shí)現(xiàn)圖片懶加載引入,而后面那種則是通過(guò)靜態(tài)資源的方式將圖片進(jìn)行引入.這便是這兩種方式的區(qū)別.由于在這個(gè)dome中要實(shí)現(xiàn)圖片懶加載,所以是使用的是第二種方式引入(在第一種方式加一個(gè){eager:true}
便可以達(dá)到第二種引入方式的效果).
先來(lái)看看imgList
的輸出結(jié)果:
可以很明顯的看到default
就是圖片的路徑,那么只需要將其獲取即可
let arr=Object.values(imgList).map((item:any)=>item.default)
因?yàn)榉祷氐氖且粋€(gè)對(duì)象,所以便可以使用Object.values
來(lái)獲取到value
,再通過(guò)map
遍歷的方式獲取到其default
值
從而便獲得了其路徑,這種獲取路徑的方式還是比較輕松,且方便的.
再解決完圖片問(wèn)題之后,便是懶加載部分的實(shí)現(xiàn)了.
懶加載實(shí)現(xiàn):
關(guān)于IntersectionObserver
的屬性和方法在前面也簡(jiǎn)單的介紹了.同時(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) }
在對(duì)于前面屬性和方法的了解的加持下,看這段代碼屬實(shí)不難.其中定時(shí)器只是為了更好的去呈現(xiàn)懶加載的這個(gè)過(guò)程.
上述代碼中,通過(guò)使用vue
的矢量圖來(lái)作為默認(rèn)圖片,當(dāng)未加載時(shí),展示這張圖.看函數(shù)主體:
enr
所返回的就是每一個(gè)圖片所返回的IntersectionObserver
因?yàn)橹惶砑恿巳龔垐D片所以返回了三個(gè)對(duì)象,而所需要關(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)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
JavaScript實(shí)現(xiàn)雙向鏈表過(guò)程解析
這篇文章主要介紹了利用JavaScript實(shí)現(xiàn)雙向鏈表以及它的封裝和常用操作,文中的示例代碼講解詳細(xì),對(duì)日常的學(xué)習(xí)和工作都有一定的價(jià)值,快來(lái)和小編一起學(xué)習(xí)吧2021-12-12JS實(shí)現(xiàn)圖片無(wú)間斷滾動(dòng)代碼匯總
這篇文章主要介紹了JS實(shí)現(xiàn)圖片無(wú)間斷滾動(dòng)代碼匯總,非常實(shí)用的特效代碼,需要的朋友可以參考下2014-07-07JS DOMReady事件的六種實(shí)現(xiàn)方法總結(jié)
下面小編就為大家?guī)?lái)一篇JS DOMReady事件的六種實(shí)現(xiàn)方法總結(jié)。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2016-11-11基于cornerstone.js的dicom醫(yī)學(xué)影像查看瀏覽功能
這篇文章主要介紹了基于cornerstone.js的dicom醫(yī)學(xué)影像查看瀏覽功能,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-07-07wap圖片滾動(dòng)特效無(wú)css3元素純js腳本編寫(xiě)
手機(jī)圖片滑動(dòng)切換,網(wǎng)上有很多這樣的例子,但都借助于其他組件,讓代碼混亂的不行,本例介紹的是無(wú)css3元素純js腳本編寫(xiě)的wap圖片滾動(dòng)特效2014-08-08常見(jiàn)瀏覽器多長(zhǎng)時(shí)間會(huì)提示“腳本運(yùn)行時(shí)間過(guò)長(zhǎng)”總結(jié)
這篇文章主要介紹了常見(jiàn)瀏覽器多長(zhǎng)時(shí)間會(huì)提示“腳本運(yùn)行時(shí)間過(guò)長(zhǎng)”總結(jié),需要的朋友可以參考下2014-04-04