JavaScript實(shí)現(xiàn)圖片懶加載的六種方案
一、什么是懶加載?
懶加載是一種對網(wǎng)頁性能優(yōu)化的方式,比如,當(dāng)訪問一個(gè)網(wǎng)頁的時(shí)候,優(yōu)先顯示可視區(qū)域的圖片而不是一次加載全部的圖片,當(dāng)需要顯示時(shí),再發(fā)送請求加載圖片。
懶加載 :延遲加載,對于一個(gè)很長的頁面,優(yōu)先加載可視區(qū)域的內(nèi)容,其他部分等進(jìn)入可視區(qū)域時(shí)再加載。
二、為什么要懶加載?
懶加載是一種網(wǎng)頁性能優(yōu)化的方式,它能極大的提升用戶體驗(yàn)。比如一個(gè)頁面中有很多圖片,但是首屏只出現(xiàn)幾張,這時(shí)如果一次性把圖片全部加載出來會(huì)影響性能。這時(shí)可以使用懶加載,頁面滾動(dòng)到可視區(qū)再加載。優(yōu)化首屏加載。
一次性加載全部圖片的話,一方面會(huì)影響用戶體驗(yàn);另一方面浪費(fèi)用戶的流量,有些用戶并不想全部看完,全部加載會(huì)耗費(fèi)大量流量。 而使用圖片懶加載就會(huì)使頁面加載速度快,減輕服務(wù)器壓力,節(jié)約流量,用戶體驗(yàn)好。
當(dāng)頁面需要展示大量圖片時(shí),如果一次性渲染所有圖片,會(huì)向服務(wù)器發(fā)出大量請求,導(dǎo)致服務(wù)器響應(yīng)慢,出現(xiàn)頁面卡頓或崩潰等問題。采用懶加載技術(shù)只預(yù)先加載可視區(qū)內(nèi)的圖片,當(dāng)滾動(dòng)到其他位置時(shí),才去加載這塊區(qū)域的圖片,也可以使用比較小的loading圖片進(jìn)行占位,有效減輕服務(wù)器的壓力,加速頁面渲染,提高用戶體驗(yàn)。
小結(jié)——懶加載優(yōu)點(diǎn):
- 避免首次加載時(shí)消耗大量時(shí)間,降低頁面渲染速度,造成卡頓現(xiàn)象。
- 按需加載,避免無效圖片的加載,減輕服務(wù)器壓力,節(jié)約網(wǎng)絡(luò)資源。
三、圖片懶加載的實(shí)現(xiàn)原理
- 基本原理: 監(jiān)聽圖片是否位于頁面的可視區(qū)域內(nèi),若在則加載圖片,不在則不加載圖片
- 實(shí)現(xiàn)方案: 自定義屬性-將圖片真實(shí)地址 url 存儲在自定義屬性中,當(dāng)監(jiān)聽到圖片進(jìn)入可視區(qū) 域 時(shí),將自定義屬性值賦值給 img 的 src 屬性
四、圖片懶加載實(shí)現(xiàn)方式
圖像是頁面的一部分,它會(huì)提前開始加載。一旦瀏覽器在源代碼中看到它們,就會(huì)提示下載。即使圖像被隱藏,即使它位于一個(gè)非常長的頁面的底部,也會(huì)提前加載。
3.1 方案一:設(shè)置 img 標(biāo)簽屬性 loading=“lazy”
設(shè)置 loading="lazy"允許瀏覽器,延遲加載屏幕外圖像 img 和 iframe,直到用戶滾動(dòng)到它們附近。
loading屬性支持下面這幾個(gè)值:
① lazy:圖片或框架懶加載,也就是元素資源快要被看到的時(shí)候加載。
② eager:圖片或框架無視一切進(jìn)行加載。
③ auto:默認(rèn)值。
圖片或框架基于瀏覽器自己的策略進(jìn)行加載。如果HTMLImageElement或者HTMLIFrameElement元素沒有顯式地設(shè)置loading屬性或者loading屬性的值不合法,則都被當(dāng)作’auto’處理。
<img src="" loading="lazy"/> <iframe src="" loading="lazy"/>
- Lazy loading加載數(shù)量與屏幕高度有關(guān),高度越小加載數(shù)量越少,但并不是線性關(guān)系。
- Lazy loading加載數(shù)量與網(wǎng)速有關(guān),網(wǎng)速越慢,加載數(shù)量越多,但并不是線性關(guān)系。
- 滾動(dòng)即會(huì)觸發(fā)圖片懶加載,而不是滾動(dòng)一屏后再去加載。
- 窗口resize尺寸變化也會(huì)觸發(fā)圖片懶加載,當(dāng)屏幕高度從小變大的時(shí)候。
3.1.1 loading 屬性的兼容
loading 屬性的兼容性如下:

3.1.2 如何判斷當(dāng)前瀏覽器是否支持loading=”lazy”?
下面三種方法都可以:
var isSupportLoading = 'loading' in document.createElement('img');var isSupportLoading = 'loading' in new Image();
var isSupportLoading = 'loading' in HTMLImageElement.prototype;
例:您可以通過檢查HTMLImageElement.prototype上是否存在loading屬性來判斷當(dāng)前瀏覽器是否支持loading="lazy"特性。以下是一個(gè)簡單的JavaScript代碼示例:
function isLazyLoadingSupported() {
// 檢查'loading'屬性是否在HTMLImageElement.prototype上定義
return 'loading' in HTMLImageElement.prototype;
}
if (isLazyLoadingSupported()) {
console.log('Lazy loading is supported.');
} else {
console.log('Lazy loading is not supported.');
}如果isLazyLoadingSupported()函數(shù)返回true,則當(dāng)前瀏覽器支持loading="lazy";如果返回false,則不支持。
3.1.3. 如何獲取loading屬性值
var attrLoading = img.loading;
如果瀏覽器并不支持原生的loading懶加載,則會(huì)返回undefined,例如在Firefox瀏覽器下
3.2 方案二:利用JS監(jiān)聽scroll滾動(dòng)事件
3.2.1. 實(shí)現(xiàn)原理
監(jiān)聽scroll事件,獲取 img 元素相對于視口的頂點(diǎn)位置 el.getBoundingClientRect().top,只要這個(gè)值小于瀏覽器的高度 window.innerHeight 就說明進(jìn)入可視區(qū)域,當(dāng)圖片進(jìn)入可視區(qū)域時(shí)再去加載圖片資源。
圖片剛開始顯示的是默認(rèn)圖片,當(dāng)進(jìn)入可視區(qū)域時(shí),用 data-src 的真實(shí)圖片地址賦值給 src。
3.2.2. 實(shí)現(xiàn)方案
① 首先給圖片一個(gè)占位資源:
<img src="default.jpg" data-src="http://www.xxx.com/target.jpg" />
② clientHeight、scrollTop 和 offsetTop

屬性介紹
獲得瀏覽器窗口(視口)大小: 2組:
1、獲取文檔顯示區(qū) / 網(wǎng)頁可見區(qū)域大小
① 對于Internet Explorer9+、Chrome、Firefox、Opera 以及 Safari
window.innerWidth、window.innerHeight | Window innerWidth 與 innerHeight 屬性 | 參考手冊

window.innertHeight : 瀏覽器窗口的內(nèi)部高度
- A 表示window的內(nèi)部高度,包含border、padding、margin以及水平滾動(dòng)條的高度
- B 語法:window.innertHeight
window.innerWidth: 瀏覽器窗口的內(nèi)部寬度
- A 表示window的內(nèi)部寬度,包括 border、padding、margin以及垂直滾動(dòng)條的寬度
- B 語法:window.innerWidth
② 對于 Internet Explorer 8、7、6、5
element.clientHeight、element.clientWidth
document.body.clientHeight : 表示的是<body>元素的內(nèi)容區(qū)域高度
- A 表示的是<body>元素的內(nèi)容區(qū)域高度,包含padding 不包含 border 和 margin以及水平滾動(dòng)條的高度
- B 語法:element.clientHeight
document.body.clientWidth : 表示的是<body>元素的內(nèi)容區(qū)域?qū)挾?/p>
- A 表示的是<body>元素的內(nèi)容區(qū)域?qū)挾龋?strong>包含padding 不包含 border 和 margin以及垂直滾動(dòng)條的寬度
- B 語法:document.body.clientWidth
或者
document.documentElement.clientHeight:表示的是整個(gè)視口的高度
- A 表示的是整個(gè)視口的高度,即整個(gè)網(wǎng)頁的可視區(qū)域高度,包含padding 不包含 border 和 margin以及水平滾動(dòng)條的高度
- B 語法:document.documentElement.clientHeight
document.documentElement.clientWidth:表示的是整個(gè)視口的寬度
- A 表示的是整個(gè)視口的寬度,即整個(gè)網(wǎng)頁的可視區(qū)域?qū)挾龋?strong>包含padding 不包含 border 和 margin以及垂直滾動(dòng)條的寬度
- B 語法:document.documentElement.clientWidth
實(shí)用的獲取頁面大小的瀏覽器兼容性JavaScript 方案(涵蓋所有瀏覽器):
var w=window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth; var h=window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight;
補(bǔ):document.documentElement.clientHeight與document.body.clientHeight的主要區(qū)別在于它們代表的網(wǎng)頁區(qū)域不同。
- document.documentElement.clientHeight 表示的是整個(gè)視口的高度,即整個(gè)網(wǎng)頁的可視區(qū)域高度。它包括了padding但排除了border、水平滾動(dòng)條和margin的高度。
- document.body.clientHeight 表示的是<body>元素的內(nèi)容區(qū)域高度,通常不包括滾動(dòng)條的高度。如果<body>元素沒有設(shè)置高度或者其高度小于其內(nèi)部內(nèi)容的高度,則可能會(huì)顯示不全。
影響這兩個(gè)屬性值的主要因素包括:
- CSS設(shè)置:如果<body>元素的CSS高度被設(shè)置為100%,并且包含了所有的內(nèi)容高度,那么document.body.clientHeight將反映整個(gè)視口的高度。相反,如果<html>元素的CSS高度被設(shè)置為100%,而<body>元素的高度未明確設(shè)置,那么document.documentElement.clientHeight將反映整個(gè)視口的高度,而document.body.clientHeight可能為0或小于視口高度。
- DOCTYPE聲明:缺少DOCTYPE聲明可能會(huì)導(dǎo)致document.documentElement.clientHeight為0,因?yàn)闉g覽器可能無法正確解析文檔類型,從而影響元素的默認(rèn)顯示和尺寸計(jì)算。
實(shí)際應(yīng)用中的注意事項(xiàng):
- 在開發(fā)過程中,應(yīng)注意DOCTYPE的聲明和CSS的設(shè)置,以確保頁面布局的正確顯示。如果需要獲取整個(gè)視口的高度,應(yīng)使用document.documentElement.clientHeight;如果需要獲取<body>元素的內(nèi)容高度,應(yīng)確保<body>元素的CSS高度設(shè)置正確。
- 在調(diào)試頁面布局時(shí),可以使用瀏覽器的開發(fā)者工具查看這些屬性的值,幫助定位問題所在
補(bǔ):document.body.clientWidth和window.innerWidth的主要區(qū)別在于是否包含滾動(dòng)條和邊框。
document.body.clientWidth表示瀏覽器窗口中文檔主體部分的視口寬度,這個(gè)值包括了文檔主體的內(nèi)容區(qū)域?qū)挾龋话L動(dòng)條的寬度。如果文檔主體有邊框,這個(gè)值也不包括邊框的寬度。相反,window.innerWidth表示瀏覽器窗口的內(nèi)視口寬度,這個(gè)值包括了視口內(nèi)部的全部寬度,即包括了滾動(dòng)條的寬度(如果存在的話)。
此外,document.body.clientWidth和window.innerWidth的區(qū)別還受到
文檔模式的影響。在混雜模式(BackCompat)下,document.body.clientWidth和window.innerWidth的值可能不同,因?yàn)榛祀s模式下文檔主體的寬度計(jì)算不包括滾動(dòng)條。而在標(biāo)準(zhǔn)模式(CSS1Compat)下,兩者的值通常是相同的,因?yàn)榇藭r(shí)文檔的寬度計(jì)算包括了滾動(dòng)條
2、完整窗口大小: window.outerWidth window.outerHeight

offsetTop : 距離父級元素頂部的高度
- A 表示當(dāng)前元素相對于其offsetParent元素的頂部內(nèi)邊距的距離
- B 語法:element.offsetTop
scrollTop : 網(wǎng)頁被卷去的距離
A 表示在有滾動(dòng)條時(shí),滾動(dòng)條向下滾動(dòng)的距離也就是元素頂部被遮住部分的高度
B 語法:element.scrollTop
③ 接著,通過監(jiān)聽 scroll 事件來判斷圖片是否到達(dá)視口
let img = document.getElementsByTagName("img");
let num = img.length;
let count = 0; //存儲圖片加載到的位置,避免每次都從第一張圖片開始遍歷
lazyload(); // 首次加載別忘了顯示圖片
window.addEventListener('scroll', throttle(lazyload, 200)); // throttle是節(jié)流函數(shù),自己實(shí)現(xiàn)一下
//offsetTop是元素與offsetParent的距離,循環(huán)獲取直到頁面頂部
function getTop(el) {
var T = el.offsetTop;
while(el = el.offsetParent) {
T += el.offsetTop;
}
return T;
}
function lazyload() {
let viewHeight = document.documentElement.clientHeight || document.body.clientHeight;//視口高度
let scrollTop = document.documentElement.scrollTop || document.body.scrollTop;//滾動(dòng)條卷去的高度
for(let i = count; i <num; i++) {
// 元素現(xiàn)在已經(jīng)出現(xiàn)在視口中
if(getTop(img[i]) < scrollTop + viewHeight) {
if(img[i].getAttribute("src") !== "default.jpg") continue;
img[i].src = img[i].getAttribute("data-src");
count ++;
} else {
break; // 提早退出
}
}
}offsetParent 就是距離該子元素最近的進(jìn)行過定位的父元素(position:absolute或relative 或fixed),如果其父元素中不存在定位,則offsetParent為:body元素
小結(jié):用JS監(jiān)測這個(gè)方式主要是利用整體距離實(shí)現(xiàn)
(1)屬性介紹:參看上面
(2)實(shí)現(xiàn)方法
可以用image.offsetTop <= document.documentElement.clientHeight + document.documentElement.scrollTop 判斷圖片是否可以在可視區(qū)域內(nèi)。即判斷圖像的offsetTop(距離頂部的高度)- scrollTop(頁面被卷去的高度)<=window.innerHeight(可視區(qū)高度)才加載
- 圖片元素位置的頂部距離:offsetTop
- 滾動(dòng)距離的最下端:scrollTop+clientHeight
// html 標(biāo)簽結(jié)構(gòu) <img data-src="./public/image/VCG211430870249.jpg" src="./public/image/默認(rèn).jpg" alt=""> <img data-src="./public/image/VCG211430987515.jpg" src="./public/image/默認(rèn).jpg" alt=""> <img data-src="./public/image/VCG211431054751.jpg" src="./public/image/默認(rèn).jpg" alt=""> <img data-src="./public/image/VCG211435102490.jpg" src="./public/image/默認(rèn).jpg" alt=""> <img data-src="./public/image/VCG211438229829.jpg" src="./public/image/默認(rèn).jpg" alt=""> <img data-src="./public/image/VCG211438109615.jpg" src="./public/image/默認(rèn).jpg" alt="">
<script>
// 1 獲取全部圖片的DOM節(jié)點(diǎn)
// 注意:querySelectorAll 值為偽數(shù)組利用擴(kuò)展運(yùn)算符轉(zhuǎn)為真數(shù)組
const images = [...document.querySelectorAll('img')]
// 2 監(jiān)聽頁面滾動(dòng)事件
window.addEventListener('scroll', lazyLoad)
// 3 定義頁面滾動(dòng)的處理函數(shù)
function lazyload(e) {
// 3.1 獲取屏幕的可視高度
const clientHeight = document.documentElement.clientHeight
// 3.2 獲取屏幕的滾動(dòng)距離
const scrollTop = document.documentElement.scrollTop
for (let i = 0; i < images.length; i++) {
if (images[i].offsetTop < clientHeight + scrollTop) {
images[i].setAttribute('src', images[i].getAttribute('data-src'))
}
}
}
</script>3.3 方案三:利用元素的 getBoundingClientRect 方法實(shí)現(xiàn)
getBoundingClientRect() 方法返回元素相對視口左上角的偏移量以及元素本身長寬,單位:px。

修改上述 lazyload 函數(shù)
function lazyload() {
let viewHeight = document.documentElement.clientHeight || document.body.clientHeight;
for (let i = count; i < num; i++) {
// 元素現(xiàn)在已經(jīng)出現(xiàn)在視口中
if (img[i].getBoundingClientRect().top < viewHeight) {
if (img[i].getAttribute("src") !== "default.jpg") continue;
img[i].src = img[i].getAttribute("data-src");
count++;
} else {
break;
}
}
}小結(jié):我們再來舉個(gè)例子,總結(jié)一下利用getBoundingClientRect 方法實(shí)現(xiàn)圖片懶加載。
(1)屬性介紹:
利用 getBoundingClientRect()方法實(shí)時(shí)獲取物體的動(dòng)態(tài)位置

(2)實(shí)現(xiàn)方法:
步驟 1:監(jiān)聽頁面滾動(dòng)事件,lazyLoad為頁面滾動(dòng)時(shí)的處理函數(shù),在本節(jié)為處理圖片懶加載。
步驟 2:判斷圖片是否處于可視區(qū)域內(nèi)
(1)若距離頂部top(或bottom)小于頁面的整體高度window.innerHeight
(2)若距離左側(cè)left(或右側(cè)right)小于頁面的整體寬度window.innerWidth
(3)同時(shí)圖片的底部bottom (或頂部top) 與圖片的右側(cè)right(左側(cè)left)距頁面頂部、左側(cè)的距離均大于0,則說明該圖在屏幕的可視區(qū)域內(nèi)。

為了提高復(fù)用性,我們可以將它封裝成一個(gè)自定義函數(shù)isVisible,將每張圖片作為參數(shù)傳入該函數(shù),并返回true或false
// 可視區(qū)域判斷函數(shù)
function isVisible(img) {
// 判斷是否在可視區(qū)域,并返回true或false
const imgRect = img.getBoundingClientRect() // getBoundingClientRect 獲取圖片的動(dòng)態(tài)信息
return imgRect.bottom > 0 && imgRect.top < (window.innerHeight|| document.documentElement.clientHeight) && imgRect.right > 0 && imgRect.left < (window.innerWidth||document.documentElement.clientWidth)
}步驟 3:定義圖片懶加載時(shí)的處理事件,監(jiān)聽所有的img,判斷該img是否處于可視范圍內(nèi)。
querySelectorAll 獲取的元素為類數(shù)組對象,需要轉(zhuǎn)為真數(shù)組,否則無法使用數(shù)組的某些方法
// 獲取所有的img元素,并利用擴(kuò)展運(yùn)算符轉(zhuǎn)為真數(shù)組
const images = [...document.querySelectorAll('img')]
步驟 4:對每張圖片進(jìn)行監(jiān)聽,利用自定義函數(shù)isVisible判斷是否在可視區(qū)域內(nèi)
(1)若處于可視區(qū)域:將自定義的data-src值,賦值給真正的src屬性值,其中 data-src存儲圖片的URL地址,并刪除該元素防止重復(fù)加載
(2)若不處于可視區(qū)域:return 不做處理
// 利用循環(huán)判斷每張圖片是否屬于可視區(qū)域
function lazyLoad(){
for (let i = 0; i < images.length; i++) {
// isVisible是否該圖片位于可視區(qū)域 返回true 或false
if (isVisible(images[i])) {
// 將元素的自定義屬性 data-src 賦值給元素的 src 屬性
// 等價(jià)于:img.setAttribute('src', img.getAttribute('data-src'))
images[i].src = images[i].dataset.src
// 防止重復(fù)被遍歷 加載完之后 刪除元素不再加載
images.splice(i, 1)
i--
}
}
}
lazyLoad()getBoundingClientRect()方法的缺點(diǎn):這個(gè)屬性頻繁計(jì)算會(huì)引發(fā)頁面的重繪,可能會(huì)對頁面的性能造成影響。
3.4. 方案四:IntersectionObserver
有兼容性問題。這是瀏覽器內(nèi)置的一個(gè)API,實(shí)現(xiàn)了監(jiān)聽window的scroll事件、判斷是否在視口中以及節(jié)流三大功能。
let img = document.getElementsByTagName("img");
const observer = new IntersectionObserver(changes => {
//changes 是被觀察的元素集合
for(let i = 0, len = changes.length; i < len; i++) {
let change = changes[i];
// 通過這個(gè)屬性判斷是否在視口中
if(change.isIntersecting) {
const imgElement = change.target;
imgElement.src = imgElement.getAttribute("data-src");
observer.unobserve(imgElement);
}
}
})
Array.from(img).forEach(item => observer.observe(item));這樣就很方便地實(shí)現(xiàn)了圖片懶加載,當(dāng)然這個(gè)IntersectionObserver也可以用作其他資源的預(yù)加載,功能非常強(qiáng)大。原文鏈接:https://blog.csdn.net/qq_44741577/article/details/139324747
小結(jié):關(guān)于IntersectionObserver
Intersection Observer是一個(gè)比較新的api,他允許你追蹤目標(biāo)元素與其祖先元素或視窗的交叉狀態(tài),用他來檢測圖片是否進(jìn)入視口非常方便,不用再像之前綁定事件、計(jì)算距離等。
(1)屬性介紹:
- 利用Intersection Observer實(shí)例上的observe和unobserve方法,注冊或取消監(jiān)聽事件。
- 利用isIntersecting方法,判斷該圖片是否處于圖片與屏幕可視區(qū)域的交叉范圍內(nèi)。
- 注意:Intersection Observer實(shí)例會(huì)監(jiān)聽交叉狀態(tài),即出現(xiàn)和消失(觸發(fā)兩次),出現(xiàn)交叉狀態(tài)后會(huì)去調(diào)用new的時(shí)候傳入的callback回調(diào)函數(shù)
(2)實(shí)現(xiàn)方法:
步驟 1: 監(jiān)聽頁面滾動(dòng)事件,lazyLoad為頁面滾動(dòng)時(shí)的處理函數(shù),在本節(jié)為處理圖片懶加載。
window.addEventListener('scroll', lazyLoad)步驟 2: 創(chuàng)建圖片與可視區(qū)域交叉實(shí)例
callback:
- 此為傳入的回調(diào)函數(shù),用于當(dāng)處于交叉狀態(tài)改變時(shí)進(jìn)行的處理函數(shù)
- 該函數(shù)會(huì)被觸發(fā)2次:圖片進(jìn)入視野時(shí)+圖片離開視野時(shí)
const observer = new IntersectionObserver(callback)
步驟 3: 利用observer實(shí)例上的.observe(img)方法,給每張圖片綁定觀察事件
// 給每一個(gè)圖片綁定觀察方法
imagess.forEach(img => {
// 圖片進(jìn)入視野+離開視野時(shí)會(huì)觸發(fā)callback回調(diào)函數(shù)
observer.observe(img)
})步驟 4: 定義圖片的懶加載事件
imgArr:
- 可以獲得包含所有圖片的
isIntersecting屬性的集合,該屬性可判斷是否在交叉區(qū)域內(nèi) target為該圖片的標(biāo)簽元素

// callback 接收的參數(shù)為帶有監(jiān)聽所有圖片交叉屬性的集合
const callback = (imgArr) => {
console.log("視圖交叉時(shí)觸發(fā),離開交叉時(shí)也觸發(fā)", imgArr);
imgArr.forEach((e) => {
// 判斷是否在視野區(qū)域
if (e.isIntersecting) {
e.target.src = e.target.dataset.src;
// 取消監(jiān)聽,避免重復(fù)加載同一張圖片
observer.unobserve(e.target);
}
});
};(3)完整代碼:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body>
<img data-src="./public/image/VCG211430870249.jpg" src="./public/image/默認(rèn).jpg" alt="" />
<img data-src="./public/image/VCG211430987515.jpg" src="./public/image/默認(rèn).jpg" alt="" />
<img data-src="./public/image/VCG211431054751.jpg" src="./public/image/默認(rèn).jpg" alt="" />
<img data-src="./public/image/VCG211435102490.jpg" src="./public/image/默認(rèn).jpg" alt="" />
<img data-src="./public/image/VCG211438229829.jpg" src="./public/image/默認(rèn).jpg" alt="" />
<img data-src="./public/image/VCG211438109615.jpg" src="./public/image/默認(rèn).jpg" alt="" />
<script>
// intersectionObserver 交叉觀察 : 目標(biāo)元素和可視窗口會(huì)產(chǎn)生交叉區(qū)域
const imagess = [...document.querySelectorAll("img")];
// 2.1 創(chuàng)建視覺交叉的觀察實(shí)例
const observer = new IntersectionObserver(callback);
// 2.2 給每一個(gè)圖片綁定觀察方法
imagess.forEach((img) => {
// 2.3 圖片進(jìn)入視野+離開視野時(shí)觸發(fā) - 回調(diào)
observer.observe(img);
});
// callback 接收的參數(shù)為帶有監(jiān)聽所有圖片交叉屬性的集合
const callback = (imgArr) => {
console.log("視圖交叉時(shí)觸發(fā),離開交叉時(shí)也觸發(fā)", imgArr);
imgArr.forEach((e) => {
// 判斷是否在視野區(qū)域
if (e.isIntersecting) {
e.target.src = e.target.dataset.src;
// 取消觀察追蹤,避免重復(fù)加載同一張圖片
observer.unobserve(e.target);
}
});
};
</script>
</body>
</html>3.5 方案五:利用element-ui 的<el-image>組件的lazy屬性開啟懶加載功能
使用element-ui 的<el-image v-for="url in urls" :key="url" :src="url" lazy></el-iamge>可通過lazy開啟懶加載功能,當(dāng)圖片滾動(dòng)到可視范圍內(nèi)才會(huì)加載。
具體實(shí)現(xiàn)代碼:element-ui的 <el-image> Element - The world's most popular Vue UI framework
<div class="demo-image__lazy">
<el-image v-for="url in urls" :key="url" :src="url" lazy></el-image>
</div>
<script>
export default {
data() {
return {
urls: [
'https://fuss10.elemecdn.com/a/3f/3302e58f9a181d2509f3dc0fa68b0jpeg.jpeg',
'https://fuss10.elemecdn.com/1/34/19aa98b1fcb2781c4fba33d850549jpeg.jpeg',
'https://fuss10.elemecdn.com/0/6f/e35ff375812e6b0020b6b4e8f9583jpeg.jpeg',
'https://fuss10.elemecdn.com/9/bb/e27858e973f5d7d3904835f46abbdjpeg.jpeg',
'https://fuss10.elemecdn.com/d/e6/c4d93a3805b3ce3f323f7974e6f78jpeg.jpeg',
'https://fuss10.elemecdn.com/3/28/bbf893f792f03a54408b3b7a7ebf0jpeg.jpeg',
'https://fuss10.elemecdn.com/2/11/6535bcfb26e4c79b48ddde44f4b6fjpeg.jpeg'
]
}
}
}
</script>3.6 方案六:使用vue-lazyLoad插件實(shí)現(xiàn)
使用vue-lazyLoad插件實(shí)現(xiàn),安裝【npm i vue-lazyload -S】,main.ts中進(jìn)行注冊
//main.ts
import VueLazyload from 'vue-lazyload'
app.use(VueLazyload,
{preLoad: 1.3, //預(yù)加載的寬高比loading:
loadimage:"./assets/vue.svg", //圖片加載狀態(tài)下顯示的圖片
// error: "", //圖片加載失敗時(shí)顯示的圖片
attempt: 1, // 加載錯(cuò)誤后最大嘗試次數(shù)
})頁面中通過v-lazy使用
//xx.vue
<template>
<div>
<div v-for="item in arr" :key="item">
<img v-lazy="item" width="600" height="200" alt="" />
</div>
</div>
</template>
<script lang="ts" setup>
//glob是懶加載模式,globEager靜態(tài)加載
let imageList: Record<string, { default: string }> = import.meta.glob(
"../assets/images/*.*",
{ eager: true }
);
let arr = Object.values(imageList).map((v) => v.default);
</script>
<style lang="scss" scoped></style>使用vite的兩種文件導(dǎo)入方式
- 【import.meta.glob("/xx")】方式 為懶加載模式,動(dòng)態(tài)導(dǎo)入,構(gòu)建時(shí),會(huì)分離為獨(dú)立的 chunk,該方式導(dǎo)入使用()=>import("/xx"),跟路由懶加載是一樣的導(dǎo)入方式。
- 【import.meta.globEager("/xx")】以及【import.meta.glob("/xx",{eager:true})】為靜態(tài)加載
打印imageList如圖

以上就是JavaScript實(shí)現(xiàn)圖片懶加載的六種方案的詳細(xì)內(nèi)容,更多關(guān)于JavaScript圖片懶加載的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
原生JS使用Canvas實(shí)現(xiàn)拖拽式繪圖功能
這篇文章主要介紹了原生js實(shí)現(xiàn)Canvas實(shí)現(xiàn)拖拽式繪圖,支持畫筆、線條、箭頭、三角形和圓形等等圖形繪制功能,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),需要的朋友可以參考下2019-06-06
封裝的dialog插件 基于bootstrap模態(tài)對話框的簡單擴(kuò)展
這篇文章主要介紹了基于bootstrap模態(tài)對話框的簡單擴(kuò)展,bootstrap-mzDialog插件的封裝,感興趣的小伙伴們可以參考一下2016-08-08
前端JS中sessionStorage,localStorage,IndexedDB本地存儲數(shù)據(jù)的三種方法詳解
這篇文章主要為大家詳細(xì)介紹了前端JS中sessionStorage,localStorage,IndexedDB本地存儲數(shù)據(jù)的三種方法,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以了解下2025-10-10
javascript判斷元素存在和判斷元素存在于實(shí)時(shí)的dom中的方法
本文主要介紹了javascript判斷元素存在和判斷元素存在于實(shí)時(shí)的dom中的方法。具有一定的參考價(jià)值,下面跟著小編一起來看下吧2017-01-01

