懶加載:
懶加載又稱延遲加載,該技術的理念是按需加載。在一些大廠的產品中用的比較多,因為對頁面渲染時間有嚴格限制。
應用懶加載的網站:
淘寶,京東,花瓣,美麗說...
相關概念:
網頁可視區寬(
width + padding
):
document.body.clientWidth
網頁占位寬(
width + padding + border
):
document.body.offsetWidth

clientWidth/offsetWidth示例
網頁正文全文寬:
document.body.scrollWidth
網頁正文被卷去的高度:
其他:document.documentElement.scrollTop
chrome:document.body.scrollTop
兼容寫法:document.documentElement.scrollTop || document.body.scrollTop

scrollTop兼容示例
- 獲取元素絕對位置:
offsetParent
:定位父級:離自己最近的有定位的父級元素;沒有手動設置定位父級的時候,默認定位父級為body。
element.offsetTop
:相對于父級的頂部偏移值;
element.offsetLeft
:相對于父級的左側偏移值;
不存在element.offsetRigth
和element.offsetBottom
屬性;

獲取定位值
寬高寫法相同,不一一列舉;
應用場景:
涉及到圖片,falsh資源 , iframe, 網頁編輯器(類似FCK)等占用較大帶寬,且這些模塊暫且不在瀏覽器可視區內,因此可以使用懶加載技術在某個模塊容器到達了網頁可見區域時,再使用ajax異步請求將請求內容渲染出來,避免網頁打開時加載過多資源,讓用戶等待太久。
判斷模塊是否進入可視區:
當用戶瀏覽到首屏之外的其他模塊,也就是其他模塊進入可視區時,異步加載進而渲染資源到頁面。
因此實現懶加載的關鍵點是判斷模塊是否進入可視區,也可以把可視區理解成一個模塊,首屏外的內容為一個模塊,當兩個模塊發生碰撞時即需是加載資源的時機。
盜一張圖解釋說明下兩個模塊的臨界點:

判斷模塊是否進入視口
引入一個公式,以圖二中的兩個模塊為例:
//top1 = 文檔頂部卷去的高度;
//top2 = 元素相對于頂層定位父級的offsetTop值;
//height1 = 文檔可視區的高度;
//height2 = 模塊的高度;
m1 = top1 + height1 / 2
m2 = top2 + height2 / 2
|m1 - m2| < (height1 + height2) / 2
上面的公式中height1、height2和top2都為常量,只有top1為變量;
//假設:top1 = 0,top2 = 300, width = height = 300,則:
m1 = 0 + 300 / 2 = 150;
m2 = 300 + 300 / 2 = 450;
|m1 - m2| = (height1 + height2) / 2;
//此時為臨界點,剛好相等;
//假設:top1 = 100,top2 = 300, width = height = 300,則:
m1 = 100 + 300 / 2 = 250;
m2 = 300 + 300 / 2 = 450;
|m1 - m2| < (height1 + height2) / 2;
//值小于時說明相交了;
獲取元素相對于頂層父級的絕對位置:
function getDstResource(ele){
var l = 0,t = 0, w, h;
//獲取元素占位寬高
w = ele.offsetWidth;
h = ele.offsetHeight;
while (ele.offsetParent){
//獲取元素偏移值
l += ele.offsetLeft;
t += ele.offsetTop;
ele = ele.offsetParent;
}
return {'left':l,'top':t,'width':w,'height':h};
}
完整代碼:
//獲取可視區
function getVisiableZone(){
var l,t,w,h;
l = document.documentElement.scrollLeft || document.body.scrollLeft;
t = document.documentElement.scrollTop || document.body.scrollTop;
w = document.documentElement.clientWidth;
h = document.documentElement.clientHeight;
return {'left':l,'top':t,'width':w,'height':h};
}
//獲取元素絕對位置
function getDstResource(ele){
var l = 0,t = 0, w, h;
//獲取元素占位寬高
w = ele.offsetWidth;
h = ele.offsetHeight;
while (ele.offsetParent){
//獲取元素偏移值
l += ele.offsetLeft;
t += ele.offsetTop;
ele = ele.offsetParent;
}
return {'left':l,'top':t,'width':w,'height':h};
}
//判斷兩個長方形是否交疊
function overlap(rect1,rect2){
var l1,l2,t1,t2,w,h;
l1 = rect1.left + rect1.width / 2;
l2 = rect2.left + rect2.width / 2;
t1 = rect1.top + rect1.height / 2;
t2 = rect2.top + rect2.height / 2;
w = (rect1.width + rect2.width) / 2;
h = (rect1.height + rect2.height) / 2;
return Math.abs(l1 - l2) < w && Math.abs(t1 - t2) < h;
}
//異步加載
if(overlap(getVisiableZone(),getDstResource(document.getElementById("xxx")))){
//相應的處理...
}