圖片懶加載的核心是延遲加載非首屏圖片,等其進入可視區(qū)域時才加載,提升頁面性能。具體實現(xiàn)方式包括:1.基于offsettop和window.innerheight進行簡單判斷;2.使用getboundingclientrect優(yōu)化可見性檢測;3.利用intersection observer api異步監(jiān)聽元素可見性,性能更優(yōu);4.結(jié)合requestanimationframe優(yōu)化滾動事件處理,避免頁面卡頓。SEO優(yōu)化可通過
圖片懶加載,簡單來說,就是讓頁面上的圖片不是一次性全部加載,而是等到它們進入用戶的可視區(qū)域時才加載。這樣做可以顯著提升頁面加載速度,特別是當頁面包含大量圖片時。
解決方案
實現(xiàn)圖片懶加載的核心在于監(jiān)聽圖片的滾動事件,判斷圖片是否進入可視區(qū)域。 一旦圖片進入可視區(qū)域,就將圖片的src屬性設(shè)置為真實的圖片地址,從而觸發(fā)圖片的加載。
以下提供四種實現(xiàn)懶加載的技巧:
-
基于offsetTop和window.innerHeight的簡單實現(xiàn)
這種方法是最基礎(chǔ)的,通過比較圖片距離頁面頂部的距離(offsetTop)和窗口的內(nèi)部高度(window.innerHeight)以及滾動條滾動的距離來判斷圖片是否可見。
function lazyLoad() { const images = document.querySelectorAll('img[data-src]'); images.forEach(img => { if (img.offsetTop < window.innerHeight + window.scrollY) { img.src = img.dataset.src; img.removeAttribute('data-src'); // 防止重復(fù)加載 } }); } // 監(jiān)聽滾動事件 window.addEventListener('scroll', lazyLoad); // 頁面加載完成時執(zhí)行一次 document.addEventListener('DOMContentLoaded', lazyLoad);
這個方法雖然簡單,但效率相對較低,每次滾動都會遍歷所有圖片。
-
使用getBoundingClientRect優(yōu)化判斷
getBoundingClientRect方法可以獲取元素相對于視口的位置信息,避免了計算offsetTop和scrollY的麻煩,也更準確。
function lazyLoad() { const images = document.querySelectorAll('img[data-src]'); images.forEach(img => { const rect = img.getBoundingClientRect(); if (rect.top <= window.innerHeight && rect.bottom >= 0 && rect.left <= window.innerWidth && rect.right >= 0) { img.src = img.dataset.src; img.removeAttribute('data-src'); } }); } window.addEventListener('scroll', lazyLoad); document.addEventListener('DOMContentLoaded', lazyLoad);
這種方法相對更高效,因為getBoundingClientRect是瀏覽器原生方法,性能較好。
-
利用Intersection Observer API實現(xiàn)
Intersection Observer API是專門為監(jiān)聽元素可見性而設(shè)計的,性能更高,也更簡潔。
const images = document.querySelectorAll('img[data-src]'); const observer = new IntersectionObserver((entries, observer) => { entries.forEach(entry => { if (entry.isIntersecting) { const img = entry.target; img.src = img.dataset.src; img.removeAttribute('data-src'); observer.unobserve(img); // 停止監(jiān)聽已加載的圖片 } }); }); images.forEach(img => { observer.observe(img); });
Intersection Observer API的優(yōu)勢在于它是異步的,不會阻塞主線程,而且可以設(shè)置閾值,控制圖片在進入可視區(qū)域多少比例時才加載。
-
結(jié)合requestAnimationFrame優(yōu)化滾動事件處理
頻繁的滾動事件處理可能會導致頁面卡頓。 使用requestAnimationFrame可以將滾動事件處理函數(shù)推遲到下一次瀏覽器重繪之前執(zhí)行,從而提高性能。
let ticking = false; function lazyLoad() { if (!ticking) { requestAnimationFrame(function() { // 上面的懶加載邏輯 ticking = false; }); ticking = true; } } window.addEventListener('scroll', lazyLoad); document.addEventListener('DOMContentLoaded', lazyLoad);
requestAnimationFrame可以確保動畫流暢,避免掉幀。
圖片懶加載如何處理SEO優(yōu)化?
懶加載雖然提升了用戶體驗,但也可能影響SEO。搜索引擎爬蟲可能無法執(zhí)行JavaScript,導致無法加載所有圖片。解決辦法:
-
使用 在
標簽中使用
@@##@@ <noscript>@@##@@</noscript>
-
使用服務(wù)器端渲染(SSR): 在服務(wù)器端渲染頁面,確保搜索引擎爬蟲可以獲取完整的html內(nèi)容,包括所有圖片。
-
使用Google推薦的懶加載方式: Google推薦使用loading=”lazy”屬性,這是一個瀏覽器原生的懶加載屬性,搜索引擎可以識別。
@@##@@
如何處理懶加載圖片的占位問題?
在圖片加載完成之前,需要為圖片預(yù)留空間,避免頁面布局發(fā)生跳動。常見的做法:
-
使用固定寬高: 為
標簽設(shè)置固定的寬度和高度。
-
使用css aspect-ratio屬性: 設(shè)置圖片的寬高比,讓瀏覽器自動計算高度。
img { aspect-ratio: 16 / 9; /* 設(shè)置寬高比 */ object-fit: cover; /* 圖片填充方式 */ }
-
使用占位符圖片: 使用低分辨率的占位符圖片,在圖片加載完成后替換為高清圖片。
如何選擇合適的懶加載實現(xiàn)方式?
選擇哪種懶加載實現(xiàn)方式取決于項目的具體需求和兼容性要求。
- 簡單項目或需要兼容舊版本瀏覽器: 可以選擇基于offsetTop或getBoundingClientRect的實現(xiàn)方式。
- 現(xiàn)代項目且對性能要求較高: 推薦使用Intersection Observer API。
- 需要更精細的控制和優(yōu)化: 可以結(jié)合requestAnimationFrame來處理滾動事件。
- 如果主要目標是提升Lighthouse得分,且沒有兼容性問題: 直接使用loading=”lazy”屬性。
總之,選擇合適的懶加載實現(xiàn)方式需要綜合考慮性能、兼容性和SEO等因素。