日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

lazyload延迟加载组件

發(fā)布時(shí)間:2025/4/14 编程问答 34 豆豆
生活随笔 收集整理的這篇文章主要介紹了 lazyload延迟加载组件 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

lazyload現(xiàn)在網(wǎng)上已經(jīng)用的很多(淘寶商城,新浪微博等等),先放demo:mylazyLoad.zip?

效果:

<div id="redbox1" οnclick="alert('js執(zhí)行了')" class="redbox">點(diǎn)擊我</div> <div class="bluebox"></div> <div class="redbox"></div> <div class="bluebox"></div> <div class="redbox"></div> <div class="bluebox"></div> <div class="redbox"></div> <div class="bluebox"></div> <div class="redbox"></div> <div class="bluebox"></div> <div class="redbox"></div> <div class="bluebox"></div> <div class="redbox"></div> <div class="bluebox"></div> <div class="redbox"></div> <div class="bluebox"></div> <div class="redbox"></div> <div class="bluebox"></div> <div class="redbox"></div> <div class="bluebox"></div> <div class="redbox"></div> <div class="bluebox"></div> <div class="redbox"></div> <div class="bluebox"></div> <div class="redbox"></div> <div class="bluebox"></div> <div class="redbox"></div> <div class="bluebox"></div> <div class="redbox"></div> <div class="bluebox"></div> <div class="redbox"></div> <div class="bluebox"></div> <div class="redbox"></div> <div class="bluebox"></div> <div class="redbox"></div> <div class="bluebox"></div> <div class="redbox"></div> <div class="bluebox"></div> <div class="redbox"></div> <div class="bluebox"></div> <div class="redbox"></div> <div class="bluebox"></div> <div class="redbox"></div> <div class="bluebox"></div> <div class="redbox"></div> <div class="bluebox"></div> <div class="redbox"></div> <div class="bluebox"></div> <div class="redbox"></div> <div class="bluebox"></div> <div class="redbox"></div> <div class="bluebox"></div> <div class="redbox"></div> <div class="bluebox"></div> <div class="redbox"></div> <div class="bluebox"></div> <div class="redbox"></div> <div class="bluebox"></div> <div class="redbox"></div> <div class="bluebox"></div> <div class="redbox"></div> <div class="bluebox"></div> <div class="redbox"></div> <div class="bluebox"></div> <div class="redbox"></div> <div class="bluebox"></div> <div class="redbox"></div> <div class="bluebox"></div> <div class="redbox"></div> <div class="bluebox"></div> <div class="redbox"></div> <div class="bluebox"></div> <div class="redbox"></div> <div class="bluebox"></div> <div class="redbox"></div> <div class="bluebox"></div> <div class="redbox"></div> <div class="bluebox"></div> <div class="redbox"></div> <div class="bluebox"></div> <div class="redbox"></div> <div class="bluebox"></div> <div class="redbox"></div> <div class="bluebox"></div> <div class="redbox"></div> <div class="bluebox"></div> <div class="redbox"></div> <div class="bluebox"></div> <div class="redbox"></div> <div class="bluebox"></div> <div class="redbox"></div> <div class="bluebox"></div> <div class="redbox"></div> <div class="bluebox"></div> <div class="redbox"></div> <div class="bluebox"></div> <div class="redbox"></div> <div class="bluebox"></div> <div class="redbox"></div> <div class="bluebox"></div> <div class="redbox"></div> <div class="bluebox"></div> <div class="redbox"></div> <div class="bluebox"></div> <div class="redbox"></div> <div class="bluebox"></div> <div class="redbox"></div> <div class="bluebox"></div> <div class="redbox"></div> <div class="bluebox"></div> <div class="redbox"></div> <div class="bluebox"></div> <div class="redbox"></div> <div class="bluebox"></div> <div class="redbox"></div> <div class="bluebox"></div> <div class="redbox"></div> <div class="bluebox"></div> <div class="redbox"></div> <div class="bluebox"></div> <div class="redbox"></div> <div class="bluebox"></div> <div class="redbox"></div> <div class="bluebox"></div> <div class="redbox"></div> <div class="bluebox"></div> <div class="redbox"></div> <div class="bluebox"></div> <div class="redbox"></div> <div class="bluebox"></div> <div class="redbox"></div> <div class="bluebox"></div> <div class="redbox"></div> <div class="bluebox"></div> <div class="redbox"></div> <div class="bluebox"></div> <div class="redbox"></div> <div class="bluebox"></div> <div class="redbox"></div> <div class="bluebox"></div> <div class="redbox"></div> <div class="bluebox"></div> <div class="redbox"></div> <div class="bluebox"></div> <div class="redbox"></div> <div class="bluebox"></div> <div class="redbox"></div> <div class="bluebox"></div> <div class="redbox"></div> <div class="bluebox"></div> <div class="redbox"></div> <div class="bluebox"></div> <div class="redbox"></div> <div class="bluebox"></div> <div class="redbox"></div> <div class="bluebox"></div> <div class="redbox"></div> <div class="bluebox"></div> <div class="redbox"></div> <div class="bluebox"></div> <div class="redbox"></div> <div class="bluebox"></div> <div class="redbox"></div> <div class="bluebox"></div> <div class="redbox"></div> <div class="bluebox"></div> <div class="redbox"></div> <div class="bluebox"></div> <div class="redbox"></div> <div class="bluebox"></div> <div class="redbox"></div> <div class="bluebox"></div> <div class="redbox"></div> <div class="bluebox"></div> <div class="redbox"></div> <div class="bluebox"></div> <div class="redbox"></div> <div class="bluebox"></div> <div class="redbox"></div> <div class="bluebox"></div> <div class="redbox"></div> <div class="bluebox"></div> <div class="redbox"></div> <div class="bluebox"></div> <div class="redbox"></div> <div class="bluebox"></div> <div class="redbox"></div> <div class="bluebox"></div> <div class="redbox"></div> <div class="bluebox"></div> <div class="redbox"></div> <div class="bluebox"></div> <div class="redbox"></div> <div class="bluebox"></div> <div class="redbox"></div> <div class="bluebox"></div> <div class="redbox"></div> <div class="bluebox"></div> <div class="redbox"></div> <div class="bluebox"></div> <div class="redbox"></div> <div class="bluebox"></div> <div class="redbox"></div> <div class="bluebox"></div> <div class="redbox"></div> <div class="bluebox"></div> <div class="redbox"></div> <div class="bluebox"></div> <div class="redbox"></div> <div class="bluebox"></div> <div class="redbox"></div> <div class="bluebox"></div> <div class="redbox"></div> <div class="bluebox"></div> <div class="redbox"></div> <div class="bluebox"></div> <div class="redbox"></div> <div class="bluebox"></div> <div class="redbox"></div> <div class="bluebox"></div> <div class="redbox"></div> <div class="bluebox"></div> <div class="redbox"></div> <div class="bluebox"></div> <div class="redbox"></div> <div class="bluebox"></div> <div class="redbox"></div> <div class="bluebox"></div> <div class="redbox"></div> <div class="bluebox"></div> <div class="redbox"></div> <div class="bluebox"></div> <div class="redbox"></div> <div class="bluebox"></div> <div class="redbox"></div> <div class="bluebox"></div> <div class="redbox"></div> <div class="bluebox"></div> <div class="redbox"></div> <div class="bluebox"></div>

【基本原理】

在有大量數(shù)據(jù)加載的頁(yè)面中,我們需要一個(gè)容器,這個(gè)容器可以是瀏覽器窗口,也可以是頁(yè)面中的一個(gè)容器,在頁(yè)面加載的時(shí)候,我們可以將這容器顯示之外的內(nèi)容阻止其加載,當(dāng)我們滾動(dòng)這個(gè)容器到相應(yīng)區(qū)域的時(shí)候才將該區(qū)域內(nèi)容加載出來(lái),以此達(dá)到加快瀏覽速度的目的。

延遲加載一般分靜態(tài)和動(dòng)態(tài)兩種。

靜態(tài)的典型例子就是淘寶商城,我們?cè)谟^察淘寶商城的html時(shí)發(fā)現(xiàn),其頁(yè)面采用了大量的textarea來(lái)存放頁(yè)面元素,我們想要把頁(yè)面元素存放在html里,而又不想這些元素被解析,同時(shí)又能輕松方便的獲取,textarea正好滿足了這些條件(真不知道哪位牛人想到的)。

而動(dòng)態(tài)的可以說(shuō)就是ajax獲取數(shù)據(jù)再綁定,典型例子就是新浪微博,當(dāng)頁(yè)面滾動(dòng)到底部時(shí)觸發(fā)加載函數(shù)。

我的理解是將需要延遲加載的觸發(fā)元素存入一個(gè)數(shù)組中,當(dāng)容器scroll/resize時(shí)遍歷這個(gè)數(shù)組,如果觸發(fā)元素在視窗范圍內(nèi)就執(zhí)行加載函數(shù),并將這個(gè)元素從數(shù)組中刪除來(lái)提高效率。

【程序說(shuō)明】

一般在創(chuàng)建實(shí)例的時(shí)候,需要定義兩個(gè)屬性:elems和container,elems是觸發(fā)加載的元素集合,或者說(shuō)是加載內(nèi)容集合,container就是容器。

1.因?yàn)閑lems需要進(jìn)行刪除,所以首先需要將elems轉(zhuǎn)換為數(shù)組Array。

$A() code /*將參數(shù)轉(zhuǎn)換為數(shù)組
?*?@param?{all}?a?參數(shù)
?
*/
var?$A=function(a){
????
if(!a)return?[];
????
if(a?instanceof?Array)?return?a;
????
var?arr=[],len=a.length;
????
if(/string|number/.test(typeof?a)||a?instanceof?Function?||?len===undefined){
????????arr[
0]=a;
????}
else{
????????
for(var?i=0;i<len;i++){
????????????arr[i]
=a[i];
????????}
????}
????
return?arr;????
}
this.elems=$A(this.options.elems);/*加載對(duì)象轉(zhuǎn)換成數(shù)組*/

參數(shù)a可以是string,number,object,array,function,HTMLCollection,null。

PS:我發(fā)現(xiàn)object.length===undefined

2.container是容器,可以是window,也可以是頁(yè)面元素,所以初始化時(shí)先判斷是否是window。

container var?doc=document;
var?isWin?=?c==window||c==doc||c==null||!c.tagName||/body|html/i.test(c.tagName);/*判斷容器是否是window*/
if(isWin)c=doc.documentElement;
this.container=c;

如果不是明確的非body/html的dom元素,將都視為容器為window。

3.獲取container的顯示范圍,即容器相對(duì)于瀏覽器視窗左上角的top/bottom/left/right距離,如果是window,即瀏覽器視窗的大小。

getContainerRange /*獲取容器顯示范圍方法*/
var?_getContainerRange=isWin&&window.innerWidth?function(){
????
return?{top:0,left:0,right:window.innerWidth,bottom:window.innerHeight}
}:
function(){
????
return?_this._getRect(c);
}
this._refreshRange=function(){
????_this.range
=_getContainerRange();
}
this._refreshRange();

/*獲取元素位置參數(shù)*/
_getRect:
function(elem){
????
var?r=elem.getBoundingClientRect();/*元素到窗口左上角距離*/
????
return?{top:r.top,left:r.left,bottom:r.bottom,right:r.right}
}

?獲取瀏覽器視窗大小在IE下可以通過(guò)offsetWidth/offsetHeight獲得,但非IE瀏覽器則略有差異,好在非IE下有innerWidth/innerHeight可以使用。另外還有dom.getBoundingClientRect()這個(gè)方法,它的作用是獲得dom相對(duì)于視窗左上角的top/left/bottom/right距離,而且這個(gè)方法已經(jīng)得到所有瀏覽器的支持,大大提高了我們的效率。

PS:getBoundingClientRect可以看下http://www.cnblogs.com/qieqing/archive/2008/10/06/1304399.html?,另外談到IE下2px問(wèn)題,因?yàn)檫@里我都是用這個(gè)方法來(lái)獲取容器以及元素位置,所以這2px差異可以忽略,也許這不太嚴(yán)謹(jǐn),但同時(shí)也為了提高點(diǎn)效率考慮。

4.接下來(lái)就是給container綁定scroll/resize事件。

addEventHandler this._scrollload=function(){
????
if(!isWin){_this._refreshRange();}
????_this._doLoad();
}
this._noWinScroll=function(){?/*解決刷新時(shí)window滾動(dòng)條定位后造成range錯(cuò)誤bug*/
????_this.range
=_getContainerRange();
????removeEventHandler(window,
"scroll",_this._noWinScroll);
}
this._resizeload=function(){
????_this._refreshRange();
????_this._doLoad();
}
this.binder?=?isWin???window?:?c;
if(!isWin)addEventHandler(window,"scroll",this._noWinScroll);
addEventHandler(
this.binder,"scroll",this._scrollload);
addEventHandler(
this.binder,"resize",this._resizeload);

container是window話,scroll是不會(huì)改變container的range的,而container是元素的話,range會(huì)隨著window的scroll而改變,所以這里做分支處理。

另外當(dāng)我們講window的滾動(dòng)條滾至中間位置,再F5刷新頁(yè)面之后,滾動(dòng)條同樣會(huì)在剛剛的位置,IE下首先會(huì)將滾動(dòng)條提至頂部,再定位到剛剛的位置,這樣就出現(xiàn)了一個(gè)問(wèn)題,在第一次執(zhí)行l(wèi)azyload的時(shí)候,container的range是window滾動(dòng)條在頂部時(shí)候的值,而并非我們需要的實(shí)際值。所以我這里在非isWin情況下,給window綁定一次_noWinScroll事件,滾動(dòng)條定位后刪除這個(gè)事件。

5.下面講的是具體的判斷、執(zhí)行

_doLoad /*加載判斷,防止多次調(diào)用
?@lock鎖定,加載過(guò)程中鎖定。如果為false,執(zhí)行加載;如果為true,延遲遞歸
*/
_doLoad:
function(){
????
var?_this=this;
????
if(!this.lock){
????????
this.lock=true;
????????setTimeout(
function(){_this._loadRun()},100);
????}
else{
????????clearTimeout(
this.timer);
????????
var?self=arguments.callee;
????????
this.timer=setTimeout(function(){self.call(_this)},100);
????}
}

scroll事件在各個(gè)瀏覽器里的執(zhí)行次數(shù)不同,最好的是FF,一次滾輪滾動(dòng)只會(huì)執(zhí)行一次,而其他瀏覽器或多或少的會(huì)執(zhí)行多次。為了優(yōu)化這點(diǎn),用了一個(gè)lock判斷,當(dāng)在進(jìn)行加載函數(shù)_loadRun時(shí),我們鎖住scroll,具體方法就是"clearTimeout(this.timer);this.timer=setTimeout(function(){_this._doLoad();},100);",使用setTimeout延遲遞歸_doLoad,執(zhí)行第二次遞歸前clearTimeout上一次,這樣就能保證一次滾動(dòng)只執(zhí)行兩次,開(kāi)始一次,結(jié)束一次,中間的全部鎖住。

_loadRun /*加載運(yùn)行*/
_loadRun:
function(){
????
var?elems=this.elems;
????
if(elems.length){
????????
for(var?i=0;i<elems.length;i++){
????????????
var?rect=this._getRect(elems[i]);
????????????
var?side=this._isRange(this._inRange(rect));
????????????
if(side&&side!=0){
????????????????
if(side==1&&!this.elock){
????????????????????
this.elock=true;
????????????????????
this._onDataLoad(elems[i]);
????????????????????elems.splice(i
--,1);/*加載完之后將該對(duì)象從隊(duì)列中刪除*/
????????????????}
else{break;}
????????????}
????????}????????????
????????
if(!elems.length){
????????????
this._release();
????????}
????}
????
this.lock=false;
}
_inRange:function(rect){
????
var?range=this.range;
????
var?side={
????????v?:?rect.top
<=range.bottom???rect.bottom>=range.top???"in"?:?""?:?"bottom",/*垂直位置*/
????????h?:?rect.left
<=range.right???rect.right>=range.left???"in"?:?""?:?"right"?/*水平位置*/
????};
????
return?side;
},
_isRange:
function(side){
????
/*1:加載?-1:跳出循環(huán)?0:不加載執(zhí)行下一個(gè)*/
????
return?{
????????v:side.v?
??side.v=="in"?1:-1?:?0,
????????h:side.h?
??side.h=="in"?1:-1?:?0,
????????c:side.v
&&side.h???side.v=="in"&&side.h=="in"??1:side.v!="in"?-1:0?:?0
????}[
this.mode||"c"]
}

這里的邏輯如下:

1)遍歷elems數(shù)組,獲取元素[0]的rect,根據(jù)rect和container的range做比較,判斷元素[0]相對(duì)于container的位置("[top/left]","bottom/right","in")

????????????????

2)再根據(jù)我們的mode獲得操作類(lèi)型(-1,0,1)。-1表示在容器顯示范圍的后面,之后的元素可以不再判斷,執(zhí)行跳出循環(huán);0表示在容器顯示范圍的前面,不執(zhí)行加載,進(jìn)行下個(gè)元素的判斷;1表示在顯示范圍內(nèi),需要加載。

3)當(dāng)返回的side為1時(shí),執(zhí)行_onDataLoad(),然后從元素集合中刪除該元素,用的方法是Array.splice(index,num),同時(shí)i--,使得能準(zhǔn)確的找到下個(gè)元素。這里的elock用來(lái)鎖定元素加載,主要用在動(dòng)態(tài)ajax加載的時(shí)候,因?yàn)閯?dòng)態(tài)加載的時(shí)候,我們希望當(dāng)多個(gè)元素同時(shí)存在于container以及多次觸發(fā)scroll時(shí),只執(zhí)行第一個(gè)元素的加載。

4)然后進(jìn)行下個(gè)元素[1]的判斷,重復(fù)之前的步驟。

5)當(dāng)元素集合為空時(shí),摧毀所有的綁定。

_release _release:function(){
????removeEventHandler(
this.binder,"scroll",this._scrollload);
????removeEventHandler(
this.binder,"resize",this._resizeload);
????????
this._onDataEnd();
}

6._onDataLoad默認(rèn)情況是靜態(tài)加載。

_onDataLoad /*刪除Script字符串內(nèi)容*/
String.prototype.removeJS
=function(){
????
return?this.replace(/<script[^>]*?>([\w\W]*?)<\/script>/ig,"");
}
/*將Script字符串轉(zhuǎn)換為Script對(duì)象,返回Script?or?false*/
String.prototype.getJS
=function(){
????
var?js=this.replace(/[\s\S]*?<script[^>]*?>([\w\W]*?)<\/script>[\s\S]*?/g,"$1\r");
????
if(js==this){
????????
return?false;
????}
else{
????????
var?s=document.createElement("script");
????????s.text
=js;
????????
return?s;
????}
}
this._onDataLoad=this.options.ondataload?||?function(elem){?/*數(shù)據(jù)加載*/
????
var?h=elem.getElementsByTagName("textarea");
????
if(h.length){
????????
var?js=h[0].value.getJS();?/*解決innerHTML?javascript不執(zhí)行的問(wèn)題*/
????????
if(js){
????????????elem.innerHTML
=h[0].value.removeJS();?/*刪除javascript字符串*/
????????????elem.appendChild(js);
????????}
else{
????????????elem.innerHTML
=h[0].value;
????????}
????}
????
this.elock=false;
}

這里主要說(shuō)的是html里的javascript代碼問(wèn)題,通過(guò)innerHTML的javascript代碼是不會(huì)執(zhí)行的,所以在這里需要提取html里的script代碼,創(chuàng)建一個(gè)script元素,appendChild進(jìn)容器內(nèi)才能執(zhí)行。

【總結(jié)】

總的來(lái)說(shuō)在優(yōu)化上以及需求的考慮上都有了提高。也越來(lái)越喜歡用自己整理的框架去組件,這樣就能做到不僅知其然而且還能知其所以然。希望今后能在算法上得到指點(diǎn)。

demo丑了點(diǎn),大家湊合湊合(^。^)y-~~

【完整代碼】

javascript library //?JavaScript?Document
/*
my?javascript?library?v1.2*/
/*written?by?Lecaf*/
/*update?by?2011.4.12*/

/*刪除Script字符串內(nèi)容*/
String.prototype.removeJS
=function(){
????
return?this.replace(/<script[^>]*?>([\w\W]*?)<\/script>/ig,'');
}
/*將Script字符串轉(zhuǎn)換為Script對(duì)象,返回Script?or?false*/
String.prototype.getJS
=function(){
????
var?js=this.replace(/[\s\S]*?<script[^>]*?>([\w\W]*?)<\/script>[\s\S]*?/g,'$1\r');
????
if(js==this){
????????
return?false;
????}
else{
????????
var?s=document.createElement('script');
????????s.text
=js;
????????
return?s;
????}
}

/*getElementById
?*?@param?{String}?id?ID值
?
*/
var?$id?=?function(id){
????
if(typeof?id!='undefined'?&&?typeof?id?===?'string'){
????????
return?document.getElementById(id);????
????}
????
return?null;
}

/*講參數(shù)轉(zhuǎn)換為數(shù)組
?*?@param?{all}?a?參數(shù)
?
*/
var?$A=function(a){
????
if(!a)return?[];
????
if(a?instanceof?Array)?return?a;
????
var?arr=[],len=a.length;
????
if(/string|number/.test(typeof?a)||a?instanceof?Function?||?len===undefined){
????????arr[
0]=a;
????}
else{
????????
for(var?i=0;i<len;i++){
????????????arr[i]
=a[i];
????????}
????}
????
return?arr;????
}

/*注銷(xiāo)事件
?*?@param?{Object}?oTarget?對(duì)象
?*?@param?{String}?sEventType?事件類(lèi)型
?*?@param?{Function}?fnHandler?事件方法
?
*/
var?removeEventHandler=function(oTarget,?sEventType,?fnHandler)?{
????
if(oTarget.listeners[sEventType]){
????????
var?listeners=oTarget.listeners[sEventType];
????????
for(var?i=0,fn;fn=listeners[i++];){
????????????
if(fn==fnHandler){
????????????????listeners.splice(
--i,1);
????????????}
????????}
????????
if(!listeners.length&&listeners["_handler"]){
????????????oTarget.removeEventListener?
??oTarget.removeEventListener(sEventType,?listeners["_handler"],?false)?:?oTarget.detachEvent('on'?+?sEventType,?listeners["_handler"]);
????????}
????}????
}

/*添加事件
?*?@param?{Object}?oTarget?對(duì)象
?*?@param?{String}?sEventType?事件類(lèi)型
?*?@param?{Function}?fnHandler?事件方法
?
*/
var?addEventHandler=function(oTarget,?sEventType,?fnHandler)?{
????oTarget.listeners
=oTarget.listeners||{};
????
var?listeners?=?oTarget.listeners[sEventType]?=?oTarget.listeners[sEventType]||[];
????listeners.push(fnHandler);
????
if(!listeners["_handler"]){
????????listeners[
"_handler"]=function(e){
????????????
var?e=e||window.event;
????????????
for(var?i=0,fn;fn=listeners[i++];){
????????????????fn.call(oTarget,e)
????????????}
????????}
????????oTarget.addEventListener?
??oTarget.addEventListener(sEventType,?listeners["_handler"],?false)?:?oTarget.attachEvent('on'?+?sEventType,?listeners["_handler"]);
????}????
}

/*觸發(fā)事件
?*?@param?{Object}?oTarget?對(duì)象
?*?@param?{String}?sEventType?事件類(lèi)型
?
*/
var?dispatchEventHandler=function(oTarget,sEventType){
????
if(oTarget.dispatchEvent){
????????
var?e=document.createEvent('Event');
????????e.initEvent(sEventType,
true,true);
????????oTarget.dispatchEvent(e);
????}
else{
????????oTarget.fireEvent(
'on'+sEventType);
????}
}

/*json擴(kuò)展
?*?@param?{Object}?target?目標(biāo)json
?*?@param?{Object}?src?源json
?
*/
var?extendJson=function(target,src){
????
for(var?para?in?src){
????????target[para]
=src[para];
????}
????
return?target;
}

/*在目標(biāo)元素之后插入新元素?js自帶方法:?target.appendChild(newDoc);target.insertBefore(newDoc,existingChild);
?*?@param?{Document}?newEl?新元素
?*?@param?{Document}?targetEl?目標(biāo)元素
?
*/
var?insertAfter=function(newEl,targetEl){
????
var?parentEl?=?targetEl.parentNode;
????
if(parentEl.lastChild?==?targetEl){
????????parentEl.appendChild(newEl);
????}
else{
????????parentEl.insertBefore(newEl,targetEl.nextSibling);
????}
}

/*動(dòng)態(tài)加載CSS文件
?*?@param?{String}?file?css路徑
?*?@param?{String}?cssid?css?link?ID
?
*/
var?loadCSS=function?(file,cssid){
????
var?cssTag?=?cssid???document.getElementById(cssid)?:?null;
????
var?head?=?document.getElementsByTagName('head').item(0);
????
if(cssTag)?head.removeChild(cssTag);
????css?
=?document.createElement('link');
????css.href?
=?file;
????css.rel?
=?'stylesheet';
????css.type?
=?'text/css';
????
if(cssid){css.id?=?cssid;}
????head.appendChild(css);
}

/*ajax封裝
?*?@param?{Object}?options?參數(shù)集
?*?@param?{String}?url?鏈接
?*?@param?{String}?type?傳參方式?'POST'?or?'GET'(默認(rèn))
?*?@param?{Bool}?async?是否異步?true異步(默認(rèn))?false同步
?*?@param?{String}?dataType?返回?cái)?shù)據(jù)類(lèi)型?'html'(默認(rèn))?'xml'?'json'
?*?@param?{Function}?beforeSend?發(fā)送請(qǐng)求前調(diào)用函數(shù)
?*?@param?{Function}?success?請(qǐng)求成功后回調(diào)函數(shù)
?*?@param?{Function}?complete?請(qǐng)求完成后回調(diào)函數(shù)(不管成功與否)
?
*/
var?ajaxFun?=?function(options){
????
var?ajaxops={
????????url:
'',
????????type:
'GET',
????????async:
true,
????????dataType:
'html',
????????beforeSend:
null,
????????success:
function(){},
????????complete:
null
????}
????
var?ajaxops?=?extendJson(ajaxops,options);
????
if(ajaxops.url){
????????
var?xmlHttp;
????
????????
try{
????????????
//?Firefox,?Opera?8.0+,?Safari
????????????xmlHttp=new?XMLHttpRequest();
????????}
catch?(e){
????????????
//?Internet?Explorer
????????????try{
????????????????xmlHttp
=new?ActiveXObject('Msxml2.XMLHTTP');
????????????}
catch?(e){
????????????????
try{
????????????????????xmlHttp
=new?ActiveXObject('Microsoft.XMLHTTP');
????????????????}
catch?(e){
????????????????????alert(
'您的瀏覽器不支持AJAX!');
????????????????????
return?false;
????????????????}
????????????}
????????}
????????
var?requestDone=false;
????????
????????
if(!ajaxops.async&&navigator.userAgent.indexOf('Firefox')>0){
????????????xmlHttp.onload
=function(){
????????????????
if((?xmlHttp.status?>=?200?&&?xmlHttp.status?<?300?)?||?xmlHttp.status?===?304?||?xmlHttp.status?===?1223?||?xmlHttp.status?===?0){
????????????????????
var?msg;
????????????????????
switch(ajaxops.dataType){
????????????????????????
case?'html':
????????????????????????????msg
=xmlHttp.responseText;
????????????????????????????
break;
????????????????????????
case?'xml':
????????????????????????????msg
=xmlHttp.responseXML;
????????????????????????????
break;
????????????????????????
case?'json':
????????????????????????????msg
=xmlHttp.responseText;
????????????????????????????msg
=(new?Function('return?'+msg))();
????????????????????????????
break;
????????????????????????
default:
????????????????????????????msg
=xmlHttp.responseText;
????????????????????????????
break;
????????????????????}
????????????????????ajaxops.success(msg);
????????????????}
????????????????
if(ajaxops.complete?&&?!requestDone){
????????????????????ajaxops.complete(msg);
????????????????????requestDone
=true;
????????????????}
????????????}
????????}
else{
????????????xmlHttp.onreadystatechange
=function(){????????
????????????????
if(xmlHttp.readyState===4){
????????????????????
if((?xmlHttp.status?>=?200?&&?xmlHttp.status?<?300?)?||?xmlHttp.status?===?304?||?xmlHttp.status?===?1223?||?xmlHttp.status?===?0){
????????????????????????
var?msg;
????????????????????????
switch(ajaxops.dataType){
????????????????????????????
case?'html':
????????????????????????????????msg
=xmlHttp.responseText;
????????????????????????????????
break;
????????????????????????????
case?'xml':
????????????????????????????????msg
=xmlHttp.responseXML;
????????????????????????????????
break;
????????????????????????????
case?'json':
????????????????????????????????msg
=xmlHttp.responseText;
????????????????????????????????msg
=(new?Function('return?'+msg))();
????????????????????????????????
break;
????????????????????????????
default:
????????????????????????????????msg
=xmlHttp.responseText;
????????????????????????????????
break;
????????????????????????}
????????????????????????ajaxops.success(msg);
????????????????????}
????????????????????
if(ajaxops.complete?&&?!requestDone){
????????????????????????ajaxops.complete(msg);
????????????????????????requestDone
=true;
????????????????????}
????????????????}
????????????}
????????}
????????
if(ajaxops.beforeSend){
????????????ajaxops.beforeSend();
????????}
????????xmlHttp.open(ajaxops.type,ajaxops.url,ajaxops.async);
????????xmlHttp.send(
null);
????}
}

/*
?*?$class?寫(xiě)類(lèi)工具函數(shù)
?*?@param?{Function}?constructor
?*?@param?{Object}?prototype
?*?write?by?Snandy?http://www.cnblogs.com/snandy/
?
*/
var?$class?=?function(constructor,prototype)?{
????
var?c?=?constructor?||?function(){};
????
var?p?=?prototype?||?{};
????
return?function()?{????????
????????
for(var?atr?in?p)?{
????????????arguments.callee.prototype[atr]?
=?p[atr];
????????}????????????
????????c.apply(
this,arguments);
????}
}
lazyload //?JavaScript?Document
/*
Lazyload?v1.2*/
/*written?by?Lecaf*/
/*update?by?2011.4.8*/
var?Lazyload=function(options){
????
this._init(options);/*初始化*/
????
this._doLoad();/*第一次加載*/
????
if(!this.elems.length)this._release();/*如果加載元素為空,釋放*/
}
var?proto={
????
/*初始化參數(shù)*/
????_init:
function(options){
????????
this.binder=null;?/*加載容器對(duì)象*/
????????
this.range={};?/*加載容器顯示范圍*/
????????
this.elems=[];/*加載對(duì)象隊(duì)列*/
????????
this.container=null;
????????
this.mode="";
????????
this.lock=false;/*加載容器鎖定*/
????????
this.elock=false;/*加載元素鎖定*/
????????
this.timer=null;/*_doLoad計(jì)時(shí)器*/
????????
this.options={?/*定制參數(shù)*/
????????????container:window,
/*加載容器*/
????????????elems:
null,/*加載數(shù)據(jù)集合*/
????????????mode:
"v",/*加載模式?v(垂直加載)?h(水平加載)?c(交叉加載)?默認(rèn)v*/
????????????ondataload:
null,/*數(shù)據(jù)加載方式*/
????????????ondataend:
function(){}/*數(shù)據(jù)加載完畢*/
????????}
????????extendJson(
this.options,options||{});
????????
this.elems=$A(this.options.elems);/*加載對(duì)象轉(zhuǎn)換成數(shù)組*/
????????
this.mode=this.options.mode;
????????
this._onDataLoad=this.options.ondataload?||?function(elem){?/*數(shù)據(jù)加載*/
????????????
var?h=elem.getElementsByTagName("textarea");
????????????
if(h.length){
????????????????
var?js=h[0].value.getJS();?/*解決innerHTML?javascript不執(zhí)行的問(wèn)題*/
????????????????
if(js){
????????????????????elem.innerHTML
=h[0].value.removeJS();?/*刪除javascript字符串*/
????????????????????elem.appendChild(js);
????????????????}
else{
????????????????????elem.innerHTML
=h[0].value;
????????????????}
????????????}
????????????
this.elock=false;
????????}
????????
this._onDataEnd=this.options.ondataend;?/*所有內(nèi)容加載完執(zhí)行*/
????????
this._initContainer(this.options.container);/*初始化容器*/
????},
????
/*初始化容器*/
????_initContainer:
function(c){
????????
var?doc=document;
????????
var?_this=this;
????????
var?isWin?=?c==window||c==doc||c==null||!c.tagName||/body|html/i.test(c.tagName);/*判斷容器是否是window*/
????????
if(isWin)c=doc.documentElement;
????????
this.container=c;
????????
/*獲取容器顯示范圍方法*/
????????
var?_getContainerRange=isWin&&window.innerWidth?function(){
????????????
return?{top:0,left:0,right:window.innerWidth,bottom:window.innerHeight}
????????}:
function(){
????????????
return?_this._getRect(c);
????????}
????????
this._refreshRange=function(){
????????????_this.range
=_getContainerRange();
????????}
????????
this._refreshRange();
????????
this._scrollload=function(){
????????????
if(!isWin){_this._refreshRange();}
????????????_this._doLoad();
????????}
????????
this._noWinScroll=function(){?/*解決刷新時(shí)window滾動(dòng)條定位后造成range錯(cuò)誤bug*/
????????????_this.range
=_getContainerRange();
????????????removeEventHandler(window,
"scroll",_this._noWinScroll);
????????}
????????
this._resizeload=function(){
????????????_this._refreshRange();
????????????_this._doLoad();
????????}
????????
this.binder?=?isWin???window?:?c;
????????
if(!isWin)addEventHandler(window,"scroll",this._noWinScroll);
????????addEventHandler(
this.binder,"scroll",this._scrollload);
????????addEventHandler(
this.binder,"resize",this._resizeload);
????},
????
/*獲取元素位置參數(shù)*/
????_getRect:
function(elem){
????????
var?r=elem.getBoundingClientRect();/*元素到窗口左上角距離*/
????????
return?{top:r.top,left:r.left,bottom:r.bottom,right:r.right}
????},
????
/*加載判斷,防止多次調(diào)用
?????@lock鎖定,加載過(guò)程中鎖定。如果為false,執(zhí)行加載;如果為true,延遲遞歸
????
*/
????_doLoad:
function(){
????????
var?_this=this;
????????
if(!this.lock){
????????????
this.lock=true;
????????????setTimeout(
function(){_this._loadRun()},100);
????????}
else{
????????????clearTimeout(
this.timer);
????????????
var?self=arguments.callee;
????????????
this.timer=setTimeout(function(){self.call(_this)},100);
????????}
????},
????
/*加載運(yùn)行*/
????_loadRun:
function(){
????????
var?elems=this.elems;
????????
if(elems.length){
????????????
for(var?i=0;i<elems.length;i++){
????????????????
var?rect=this._getRect(elems[i]);
????????????????
var?side=this._isRange(this._inRange(rect));
????????????????
if(side&&side!=0){
????????????????????
if(side==1&&!this.elock){
????????????????????????
this.elock=true;
????????????????????????
this._onDataLoad(elems[i]);
????????????????????????elems.splice(i
--,1);/*加載完之后將該對(duì)象從隊(duì)列中刪除*/
????????????????????}
else{break;}
????????????????}
????????????}????????????
????????????
if(!elems.length){
????????????????
this._release();
????????????}
????????}
????????
this.lock=false;
????},
????
/*判斷對(duì)象相對(duì)容器位置*/
????_inRange:
function(rect){
????????
var?range=this.range;
????????
var?side={
????????????v?:?rect.top
<=range.bottom???rect.bottom>=range.top???"in"?:?""?:?"bottom",/*垂直位置*/
????????????h?:?rect.left
<=range.right???rect.right>=range.left???"in"?:?""?:?"right"?/*水平位置*/
????????};
????????
return?side;
????},
????_isRange:
function(side){
????????
/*1:加載?-1:跳出循環(huán)?0:不加載執(zhí)行下一個(gè)*/
????????
return?{
????????????v:side.v?
??side.v=="in"?1:-1?:?0,
????????????h:side.h?
??side.h=="in"?1:-1?:?0,
????????????c:side.v
&&side.h???side.v=="in"&&side.h=="in"??1:side.v!="in"?-1:0?:?0
????????}[
this.mode||"c"]
????},
????
/*釋放*/
????_release:
function(){
????????removeEventHandler(
this.binder,"scroll",this._scrollload);
????????removeEventHandler(
this.binder,"resize",this._resizeload);
????????
this._onDataEnd();
????}
}

window.onload
=function(){
????
var?Divload=$class(Lazyload,proto);
????
var?divload=new?Divload({
????????elems:document.getElementById(
"loadmain").getElementsByTagName("div"),
????????container:$id(
"loadbox"),
????????mode:
"c"
????});
????
var?Winload=$class(Lazyload,proto);
????
var?winload=new?Winload({
????????elems:$id(
"ajaxbox").getElementsByTagName("div"),
????????container:window,
????????ondataload:
function(elem){????????
????????????
var?othis=this;
????????????ajaxFun({
????????????????url:
"ajax.html",
????????????????beforeSend:
function(){
????????????????????elem.getElementsByTagName(
"p")[0].style.display="";
????????????????},
????????????????success:
function(msg){
????????????????????
var?box=document.getElementById("ajaxload");
????????????????????box.innerHTML
=box.innerHTML+msg;
????????????????},
????????????????complete:
function(){
????????????????????othis.elock
=false;
????????????????}
????????????})
????????}
????})
}

轉(zhuǎn)載于:https://www.cnblogs.com/lecaf/archive/2011/04/08/lazyload.html

總結(jié)

以上是生活随笔為你收集整理的lazyload延迟加载组件的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。