jquery lazyload延遲加載的實現原理分析
前言
懶加載技術(簡稱lazyload)並不是新技術,它是js程序員對網頁性能優化的一種方案。lazyload的核心是按需加載。在大型網站中都有lazyload的身影,例如谷歌的圖片搜索頁,迅雷首頁,淘寶網,QQ空間等。因此掌握lazyload技術是個不錯的選擇,可惜jquery插件lazy load官網()稱不支持新版瀏覽器。
lazyload在什麼場合中應用比較合適?
涉及到圖片,falsh資源,iframe,網頁編輯器(類似FCK)等佔用較大帶寬,且這些模塊暫且不在瀏覽器可視區內,因此可以使用lazyload在適當的時候加載該類資源。避免網頁打開時加載過多資源,讓用户等待太久。
如何實現lazyload?
lazyload的難點在如何在適當的時候加載用户需要的`資源(這裏用户需要的資源指該資源呈現在瀏覽器可視區域)。因此我們需要知道幾點信息來確定目標是否已呈現在客户區,其中包括:
可視區域相對於瀏覽器頂端位置; 待加載資源相對於瀏覽器頂端位置。
在得到以上兩點數據後,通過如下函數,便可得出某對象是否在瀏覽器可視區域了。
返回瀏覽器的可視區域位置
複製代碼 代碼如下:
// 返回瀏覽器的可視區域位置
function getClient(){
var l, t, w, h;
l = llLeft || llLeft;
t = llTop || llTop;
w = ntWidth;
h = ntHeight;
return { left: l, top: t, width: w, height: h };
}
返回待加載資源位置
複製代碼 代碼如下:
// 返回待加載資源位置
function getSubClient(p){
var l = 0, t = 0, w, h;
w = etWidth;
h = etHeight;
while(etParent){
l += etLeft;
t += etTop;
p = etParent;
}
return { left: l, top: t, width: w, height: h };
}
其中 函數getClient()返回瀏覽器客户區區域信息,getSubClient()返回目標模塊區域信息。此時確定目標模塊是否出現在客户區實際上是確定如上兩個矩形是否相交。
複製代碼 代碼如下:
// 判斷兩個矩形是否相交,返回一個布爾值
function intens(rec1, rec2){
var lc1, lc2, tc1, tc2, w1, h1;
lc1 = + h / 2;
lc2 = + h / 2;
tc1 = + ht / 2 ;
tc2 = + ht / 2 ;
w1 = (h + h) / 2 ;
h1 = (ht + ht) / 2;
return (lc1 - lc2) < w1 && (tc1 - tc2) < h1 ;
}
現在基本上可以實現延時加載了,接下來,我們在roll事件中編寫一些代碼監控目標區域是否呈現在客户區。
複製代碼 代碼如下:
複製代碼 代碼如下:
var div1 = lementById("div1");
roll = function(){
var prec1 = getClient();
var prec2 = getSubClient(div1);
if (intens(prec1, prec2)) {
alert("true");
}
};
我們只需要在彈出窗口的地方加載我們需要的資源。
這裏值得注意的是 : 目標對象呈現在客户區域時,會隨着滾動而不斷的彈出窗口。因此我們需要在彈出第一個窗口後取消對該區域的監測,這裏用一個數組來收集需要監測的對象,同時將監測的邏輯抽出來。同時需要注意 onscroll事件和onresize事件都會改變遊覽器可視區域信息,因此在該類事件觸發後需要重新計算,這裏用autocheck()函數實現。
增加元素 :
複製代碼 代碼如下:
複製代碼 代碼如下:
// 比較某個子區域是否呈現在瀏覽器區域
function jiance(arr, prec1, callback){
var prec2;
for (var i = th - 1; i >= 0; i--) {
if (arr[i]) {
prec2 = getSubClient(arr[i]);
if (intens(prec1, prec2)) {
callback(arr[i]);
// 加載資源後,刪除監測
arr[i];
}
}
}
}
複製代碼 代碼如下:
// 檢測目標對象是否出現在客户區
function autocheck(){
var prec1 = getClient();
jiance(arr, prec1, function(obj){
// 加載資源...
alert(rHTML);
})
}
// 子區域一
var d1 = lementById("d1");
// 子區域二
var d2 = lementById("d2");
// 需要按需加載區域集合
var arr = [d1, d2];
roll = function(){
// 重新計算
autocheck();
}
size = function(){
// 重新計算
autocheck();
}