JavaScript懶加載與預(yù)加載原理與實現(xiàn)詳解
1、懶加載
1.1、什么是懶加載
懶加載也可以叫做延遲加載,當訪問一個頁面的時候,先把img元素伙食其他元素的背景圖片路徑替換成一張大小為1*1px圖片的路徑(這樣只需要請求一次,俗稱占位圖);
只有當圖片出現(xiàn)在瀏覽器的可視區(qū)域內(nèi)時,才這只圖片真正的路徑,讓圖片顯示出來,這就是圖片懶加載。
1.2、為什么要使用懶加載
當頁面很多,內(nèi)容很豐富的時候,頁面很長,圖片較多,比如各個商城頁面,要是頁面載入就一次性加載完畢,就需要等很長的時間
1.3、懶加載的優(yōu)點
按需加載,頁面加載速度快,節(jié)約流量,用戶體驗感好,減少服務(wù)器壓力
1.4、懶加載的原理
頁面中的img元素,如果沒有src屬性, 瀏覽器就不會發(fā)出請求去下載圖片,只有通過javascript設(shè)置了圖片路徑,瀏覽器才會發(fā)送請求。
懶加載的原理就是先在頁面中把所有的圖片統(tǒng)一使用一張占位圖進行占位,把真正的路徑存在元素的"data-url"(這個名字起個自己認識好記的就行)屬性里,要用的時候就取出來放在src里面
1.5、懶加載的實現(xiàn)步驟
- 首先,不要將圖片地址放到src屬性中,而是放到其它屬性(data-origina)中。
- 頁面加載完成后,判斷圖片是否在用戶的視野內(nèi),如果在,則將data-original屬性中的值取出存放到src屬性中
1.6、懶加載的實現(xiàn)方式
<ul>
<li><img src="../img/loading.gif" alt="" data-src="../img/1.jpg"></li>
<li><img src="../img/loading.gif" alt="" data-src="../img/2.jpg"></li>
<li><img src="../img/loading.gif" alt="" data-src="../img/3.jpg"></li>
<li><img src="../img/loading.gif" alt="" data-src="../img/4.jpg"></li>
<li><img src="../img/loading.gif" alt="" data-src="../img/5.jpg"></li>
<li><img src="../img/loading.gif" alt="" data-src="../img/6.jpg"></li>
<li><img src="../img/loading.gif" alt="" data-src="../img/7.jpg"></li>
<li><img src="../img/loading.gif" alt="" data-src="../img/8.jpg"></li>
</ul>
方式1:通過 元素距離頂部的高度 - 滾動條滾動的高度 < =窗口可視化區(qū)域高度 進行判斷;

/*元素距離頂部的高度-頁面被卷去的高度<=瀏覽器可視區(qū)域的高度
如果條件滿足,就可以替換圖片的src屬性
*/
//獲取圖片
const imgArr = document.querySelectorAll("img");
//初始化執(zhí)行
lazyLoad();
//監(jiān)聽用戶是否滾動滾動條,但是這高觸發(fā)事件,所以需要結(jié)合節(jié)流優(yōu)化
window.addEventListener("scroll", throttle(lazyLoad, 2000));
function lazyLoad() {
imgArr.forEach(item => {
//1、獲取圖片距離頂部的高度
const imgOffsetTop = item.offsetTop;
//2、獲取瀏覽器的可視區(qū)域的高度
const wHeight = window.innerHeight;
//3、獲取頁面被卷去的高度
const scrollHeight = document.documentElement.scrollTop;
//判斷圖片是否將要出現(xiàn)
if (imgOffsetTop - scrollHeight <= wHeight) {
item.src = item.getAttribute("data-src");
}
})
}
//節(jié)流
function throttle(fun, time = 250) {
let lastTime = 0;//最后一次執(zhí)行的時間
return function (...args) {
const now = new Date().getTime();//獲取當前的時間
if (now - lastTime >= time) {
fun();
lastTime = now;
}
}
}方式2:getBoundingClientRect()
- 獲取元素位置, 這個方法沒有參數(shù)
- 用于獲得頁面中某個元素的左,上, 右和下分別相對瀏覽器視窗的位置。
- 是DOM元素到瀏覽器可視范圍的距離(不包含文檔卷起的部分)
- 該函數(shù)返回一個0bject對象, 該對象有6個屬性: top, lef, right, bottom , width, height;

const imgArr = document.querySelectorAll("img");
//初始化執(zhí)行
lazyLoad()
//監(jiān)聽用戶是否滾動滾動條,但是這高觸發(fā)事件,所以需要結(jié)合節(jié)流優(yōu)化
//監(jiān)聽用戶是否滾動滾動條,但是這高觸發(fā)事件,所以需要結(jié)合節(jié)流優(yōu)化
window.addEventListener("scroll", throttle(lazyLoad, 2000));
function lazyLoad() {
imgArr.forEach(item => {
//獲取圖片和頂部的高度
const imgTop = item.getBoundingClientRect().top;
//獲取瀏覽器可視化區(qū)域高度
const wHeight = window.innerHeight;
//圖片和頂部的高度小于瀏覽器窗口可視化區(qū)域的高度
if (imgTop <= wHeight) {
//getAttribute獲取自定義屬性
// item.src = item.getAttribute("data-src");
//也可以使用dataset來獲取自定義屬性的值
item.src = item.dataset.src;
}
})
}
//節(jié)流
function throttle(fun, time = 250) {
let lastTime = 0;//最后一次執(zhí)行的時間
return function (...args) {
const now = new Date().getTime();//獲取當前的時間
if (now - lastTime >= time) {
fun();
lastTime = now;
}
}
}方式3:IntersectionObserver(callback)構(gòu)造函數(shù)
callback回調(diào)觸發(fā)兩次,看見了觸發(fā),看不見也觸發(fā)。
實例有兩個方法:
- observe給元素添加觀察
- unobserve取消對元素觀察

const callback = (res) => {
//res是一個數(shù)組,所以還需要遍歷
console.log(res);
res.forEach(item => {
//isIntersecting是否在可視區(qū)域展示
if (item.isIntersecting) {
//獲取圖片的自定義屬性并賦值給src
item.target.src = item.target.dataset.src;
//替換為真是src地址后取消對它的觀察
observe.unobserve(item.target);
}
})
}
//1、實例化構(gòu)造函數(shù)
const observe = new IntersectionObserver(callback);
const imgArr = document.querySelectorAll("img");
//遍歷所有的圖片,給每個圖片添加觀察
imgArr.forEach(item => {
//觀察圖片
observe.observe(item)
})2、預(yù)加載
2.1、什么是預(yù)加載
資源預(yù)加載是另一個性能優(yōu)化技術(shù),我們可以使用該技術(shù)來預(yù)先告知瀏覽器某些資源可能在將來會被使用到。預(yù)加載簡單來說就是將所有所需的資源提前請求加載到本地,這樣后面在需要用到時就直接從緩存取資源。
2.2、為什么要使用預(yù)加載
在網(wǎng)頁全部加載之前,對一些主要內(nèi)容進行加載,以提供給用戶更好的體驗,減少等待的時間。否則,如果一個頁面的內(nèi)容過于龐大,沒有使用預(yù)加載技術(shù)的頁面就會長時間的展現(xiàn)為一片空白,直到所有內(nèi)容加載完畢。
2.3、實現(xiàn)預(yù)加載的方法
<div>
<p></p>
<img src="../img/1.jpg" alt="">
</div>
<script type="text/javascript">
const imgArr = ["../img/2.jpg", "../img/3.jpg", "../img/4.jpg", "../img/5.jpg", "../img/6.jpg", "../img/7.jpg"]
const img = document.querySelector("img");
const p = document.querySelector("p");
//定義默認的index的值
let index = 0;
p.innerHTML = `實現(xiàn)預(yù)加載的效果,我是第${index + 1}張圖片`;
img.addEventListener("click", (e) => {
if (index < imgArr.length) {
img.src = imgArr[index];
index++;
p.innerHTML = `實現(xiàn)預(yù)加載的效果,我是第${index + 1}張圖片`;
if (index < imgArr.length) {
//切換圖片后,同時讓瀏覽器提前加載下一張圖片
preLoad(imgArr[index])
}
} else {
confirm("沒有圖片了")
}
}, false)
//調(diào)用預(yù)加載函數(shù),頁面一開始就加載數(shù)組的第一個元素
preLoad(imgArr[0])
//定義預(yù)加載函數(shù)
function preLoad(src) {
//當圖片失去焦點后
img.addEventListener("load", () => {
//創(chuàng)建一個新的img標簽
const imgNew = document.createElement("img");
//給img標簽添加src屬性為我們傳進來的src
imgNew.src = src;
})
}
</script>
到此這篇關(guān)于JavaScript懶加載與預(yù)加載原理與實現(xiàn)詳解的文章就介紹到這了,更多相關(guān)JS懶加載與預(yù)加載內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Document.body.scrollTop的值總為零的快速解決辦法
這篇文章主要介紹了Document.body.scrollTop的值總為零的解決方法的相關(guān)資料,非常不錯具有參考借鑒價值,需要的朋友可以參考下2016-06-06
微信小程序van-field中的left-icon屬性自定義實現(xiàn)過程
在小程序中,我們是用 Vant 組件庫時,常常會用到 van-field 輸入框控件,今天我將跟大家分享的是 van-field 輸入框控件中的 left-icon 屬性的自定義怎么實現(xiàn),感興趣的朋友一起看看吧2023-08-08
bootstrap插件treeview實現(xiàn)全選父節(jié)點下所有子節(jié)點和反選功能
這篇文章主要為大家詳細介紹了bootstrap插件treeview實現(xiàn)全選父節(jié)點下所有子節(jié)點、反選功能,具有一定的參考價值,感興趣的小伙伴們可以參考一下2017-07-07
js setTimeout()函數(shù)介紹及應(yīng)用以倒計時為例
setTimeout() 方法用于在指定的毫秒數(shù)后調(diào)用函數(shù)或計算表達式,下面有個倒計時的示例,需要的朋友可以學習下2013-12-12
關(guān)于javascript DOM事件模型的兩件事
DOM事件模型的兩件事:事件捕捉(Event Capture)的實現(xiàn)問題以及IE的高級事件處理模型的問題。2010-07-07

