Javascript實(shí)現(xiàn)圖片懶加載的示例代碼
未做優(yōu)化實(shí)例
以下代碼僅作為示例演示給大家看,不是公司內(nèi)部代碼。
<!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 src="https://img.36krcdn.com/20190808/v2_1565254363234_img_jpg">
<img src="https://img.36krcdn.com/20190905/v2_1567641293753_img_png">
<img src="https://img.36krcdn.com/20190905/v2_1567640518658_img_png">
<img src="https://img.36krcdn.com/20190905/v2_1567642423719_img_000">
<img src="https://img.36krcdn.com/20190905/v2_1567642425030_img_000">
<img src="https://img.36krcdn.com/20190905/v2_1567642425101_img_000">
<img src="https://img.36krcdn.com/20190905/v2_1567642425061_img_000">
<img src="https://img.36krcdn.com/20190904/v2_1567591358070_img_jpg">
<img src="https://img.36krcdn.com/20190905/v2_1567641974410_img_000">
<img src="https://img.36krcdn.com/20190905/v2_1567641974454_img_000">
</body>
</html>一次性加載所有的圖片,這對(duì)瀏覽器的頁(yè)面加載是不友好的。
瀏覽器的工作機(jī)制
1.首先了解一下瀏覽器的運(yùn)行機(jī)制
當(dāng)我們?cè)L問(wèn)一個(gè)網(wǎng)頁(yè)時(shí)
- 解析HTML文檔:瀏覽器從服務(wù)器獲取HTML文檔并開(kāi)始解析,構(gòu)建DOM樹(shù)。
- 下載樣式表:瀏覽器下載CSS樣式表,并形成CSS樹(shù)。
- 渲染頁(yè)面:瀏覽器將DOM樹(shù)和CSS樹(shù)結(jié)合起來(lái),生成渲染樹(shù),并最終繪制出可見(jiàn)的頁(yè)面。
- 處理腳本:如果頁(yè)面中有JavaScript腳本,瀏覽器會(huì)執(zhí)行這些腳本。
2.雖然 JS 是單線程的,但是瀏覽器是多線程的;img 標(biāo)簽和 script 標(biāo)簽一樣都會(huì)讓瀏覽器啟動(dòng)新的下載線程去下載圖片、JS 文件等;如果頁(yè)面上同時(shí)讓很多圖片一起加載,那會(huì)讓瀏覽器啟動(dòng)很多并發(fā)任務(wù),增加瀏覽器的壓力;這就猶如上高速,車流量如果太大,就容易造成堵塞。
懶加載
要實(shí)現(xiàn)懶加載,我們需要手動(dòng)控制圖片的加載過(guò)程,而不是讓瀏覽器自動(dòng)下載所有的<img>標(biāo)簽中的圖片。
1.使用數(shù)據(jù)屬性
將實(shí)際的圖片地址存儲(chǔ)在data-src屬性中
<img data-src="https://img.36krcdn.com/20190905/v2_1567641293753_img_png">
<img data-src="https://img.36krcdn.com/20190905/v2_1567640518658_img_png">2.監(jiān)聽(tīng)滾動(dòng)事件
// 當(dāng)DOM內(nèi)容加載完成后執(zhí)行
document.addEventListener('scroll', () => {
// 調(diào)用loadImage函數(shù)
loadImage();
});3.功能函數(shù)的實(shí)現(xiàn)
// 定義 loadImage 函數(shù)
function loadImage() {
// 獲取文檔的可視區(qū)高度
let screenHeight = document.documentElement.clientHeight;
// 獲取滾動(dòng)條的位置(兼容不同瀏覽器)
let scrollTop = document.documentElement.scrollTop || document.body.scrollTop;
// 遍歷所有圖片
for(let i = 0; i < num; i++){
// 檢查當(dāng)前圖片是否在可視區(qū)內(nèi)
if(imgs[i].offsetTop<screenHeight + scrollTop){
// 獲取圖片的 src 屬性值(使用 data 屬性)
imgs[i].src = imgs[i].getAttribute('data-src');
// 更新當(dāng)前加載的圖片索引
n = i + 1;
// 檢查是否加載完所有需要懶加載的圖片
if (n === num){
// 停止監(jiān)聽(tīng)滾動(dòng)事件,進(jìn)行性能優(yōu)化
window.removeEventListener('scroll', loadImage);
}
}
}
}clientHeight用于獲取元素的可見(jiàn)高度(不包括邊框、內(nèi)邊距和外邊距)。此屬性通常用于獲取諸如窗口、文檔或元素的高度scrollTop用于獲取或設(shè)置一個(gè)元素相對(duì)于其滾動(dòng)容器的垂直滾動(dòng)距離。這個(gè)值是從元素頂部到視口頂部的距離offsetTop用于獲取元素相對(duì)于最近的帶有定位(positioned)祖先元素的頂部偏移量。如果沒(méi)有定位的祖先,則相對(duì)于文檔的頂部
優(yōu)化:懶加載進(jìn)行防抖
由于滾動(dòng)事件太敏感,容易高頻觸發(fā)懶加載函數(shù)loadImage,我們可以給它添加一個(gè)防抖的優(yōu)化操作,減少事件的觸發(fā)。
工具庫(kù)
<script src="https://cdn.bootcdn.net/ajax/libs/lodash.js/4.17.21/lodash.min.js"></script>
完整代碼
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="https://cdn.bootcdn.net/ajax/libs/lodash.js/4.17.21/lodash.min.js"></script>
</head>
<body>
<img data-price="20" data-src="https://img.36krcdn.com/20190808/v2_1565254363234_img_jpg">
<img data-src="https://img.36krcdn.com/20190905/v2_1567641293753_img_png">
<img data-src="https://img.36krcdn.com/20190905/v2_1567640518658_img_png">
<img data-src="https://img.36krcdn.com/20190905/v2_1567642423719_img_000">
<img data-src="https://img.36krcdn.com/20190905/v2_1567642425030_img_000">
<img data-src="https://img.36krcdn.com/20190905/v2_1567642425101_img_000">
<img data-src="https://img.36krcdn.com/20190905/v2_1567642425061_img_000">
<img data-src="https://img.36krcdn.com/20190904/v2_1567591358070_img_jpg">
<img data-src="https://img.36krcdn.com/20190905/v2_1567641974410_img_000">
<img data-src="https://img.36krcdn.com/20190905/v2_1567641974454_img_000">
<script>
// 獲取頁(yè)面中所有的img元素
const imgs = document.getElementsByTagName('img');
// 獲取img元素的數(shù)量
const num = imgs.length;
// 記錄當(dāng)前加載的是第幾張圖片,從0開(kāi)始
let n = 0;
// 當(dāng)DOM完全加載后,執(zhí)行l(wèi)oadImage函數(shù)
document.addEventListener('DOMContentLoaded', () => {
loadImage();
});
// 定義loadImage函數(shù)
function loadImage() {
console.log('121122');
// 獲取可視區(qū)域的高度,兼容不同瀏覽器
let screenHeight = document.documentElement.clientHeight;
// 獲取滾動(dòng)條的位置,兼容不同瀏覽器
let scrollTop = document.documentElement.scrollTop || document.body.scrollTop;
// 遍歷所有圖片
for (let i = 0; i < num; i++){
// 如果圖片的頂部位置在可視區(qū)內(nèi)
if (imgs[i].offsetTop < screenHeight + scrollTop){
// 設(shè)置圖片的src屬性
imgs[i].src = imgs[i].getAttribute('data-src');
// 更新加載的圖片索引
n = i + 1;
// 如果所有圖片都已加載,則移除scroll事件的監(jiān)聽(tīng)器,進(jìn)行性能優(yōu)化
if (n === num){
// console.log('加載完成');
// 所有圖片加載完成后,移除功能函數(shù)
window.removeEventListener('scroll', throttleLazyLoad);
}
}
}
}
// 使用Lodash的throttle函數(shù)來(lái)延遲loadImage的執(zhí)行,減少性能開(kāi)銷
const throttleLazyLoad = _.throttle(loadImage, 300);
// 添加scroll事件監(jiān)聽(tīng)器,在滾動(dòng)時(shí)執(zhí)行throttleLazyLoad
window.addEventListener('scroll', throttleLazyLoad);
</script>
</body>
</html>總結(jié)
圖片懶加載是一項(xiàng)簡(jiǎn)單而有效的前端性能優(yōu)化技術(shù),歡迎大家一起討論其他更好的方法。
到此這篇關(guān)于Javascript實(shí)現(xiàn)圖片懶加載的示例代碼的文章就介紹到這了,更多相關(guān)Javascript圖片懶加載內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
layui 實(shí)現(xiàn)table翻頁(yè)滾動(dòng)條位置保持不變的例子
今天小編就為大家分享一篇layui 實(shí)現(xiàn)table翻頁(yè)滾動(dòng)條位置保持不變的例子,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2019-09-09
用js閉包的方法實(shí)現(xiàn)多點(diǎn)標(biāo)注冒泡示例
這篇文章主要介紹了用js閉包的方法實(shí)現(xiàn)多點(diǎn)標(biāo)注冒泡,需要的朋友可以參考下2014-05-05
利用JS響應(yīng)式修改vue實(shí)現(xiàn)頁(yè)面的input值
這篇文章主要給大家介紹了關(guān)于如何利用JS響應(yīng)式修改vue實(shí)現(xiàn)頁(yè)面的input值,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或者使用JS具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-09-09
javascript 獲取所有id中包含某關(guān)鍵字的控件的實(shí)現(xiàn)代碼
獲取某容器控件中id包含某字符串的控件id列表2010-11-11
javascript特殊文本輸入框網(wǎng)頁(yè)特效
這篇文章主要為大家詳細(xì)介紹了javascript特殊文本輸入框網(wǎng)頁(yè)特效,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2016-09-09
JS實(shí)現(xiàn)select選中option觸發(fā)事件操作示例
這篇文章主要介紹了JS實(shí)現(xiàn)select選中option觸發(fā)事件操作,結(jié)合實(shí)例形式總結(jié)分析了javascript針對(duì)select下拉選中option項(xiàng)觸發(fā)事件相關(guān)操作技巧,需要的朋友可以參考下2018-07-07
基于JavaScript中字符串的match與replace方法(詳解)
下面小編就為大家介紹一下JavaScript中的字符串的match與replace方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2017-12-12
javascript得到XML某節(jié)點(diǎn)的子節(jié)點(diǎn)個(gè)數(shù)的腳本
得到XML某節(jié)點(diǎn)(pnode)的子節(jié)點(diǎn)個(gè)數(shù)(客戶端)2008-10-10
JS正則表達(dá)式修飾符中multiline(/m)用法分析
這篇文章主要介紹了JS正則表達(dá)式修飾符中multiline(/m)用法,結(jié)合實(shí)例形式分析了JS正則中多行模式multiline的功能、使用方法與相關(guān)注意事項(xiàng),需要的朋友可以參考下2016-12-12

