圖片懶加載庫echo.js源碼學習
最近不是在學習設計模式嗎,然後就看到了代理模式加載圖片的樣例,然後自己實現了一下,就發現,自己寫的這貨每次就只能加載一張圖片,而且圖片要放在哪也是個很嚴重的問題
然後就去了 gayhub 找了找了找流行的圖片懶加載庫,這一找,就找到了一個echo.j是,打開一看,源碼只有100多行吧,震驚。。,看完源碼,哎,木有上代理模式呀
仔細學習了下源碼:覺得這種做法比較適合圖片位置確定場景的吧,比如文章啊,一篇文章老長了,裏面有蠻多圖片散落在不同的地方,這樣就比較合適,有可能有很多圖片讀者都不會翻到哪裏,加載下來就浪費了
關鍵點:
1.如何判斷元素距離出現在視野裏的長度還有多少?以常見鼠標往下滾動,圖片在下面為例
靈魂畫手哈哈,,,;H1是視窗的高度,window.innerHeight可以獲得,H2就是提供給使用者設置的offsetBottom
然後祭出一個大招!element.getBoundingClientRect(),就能得到元素相對於視窗的四個距離
var H=Element.getboundingclientrect().top; var flag=H-(H1+H2);//當flag值小於0就代表可以開始加載圖片了
那麽,看看源碼裏面是怎麽寫的:
var offset = {//四個值由用戶傳入決定,默認為0 t: , b:, l: , r: }; var view = { //計算鄰界的距離 l: 0 - offset.l, t: 0 - offset.t, b: (root.innerHeight || document.documentElement.clientHeight) + offset.b, r: (root.innerWidth || document.documentElement.clientWidth) + offset.r }; var isHidden = function (element) { return (element.offsetParent === null); //element.offsetParent 表示父元素,如果為null證明沒有在添加到DOM裏面,或者position值為fixed }; var inView = function (element, view) { //判斷是否在視圖中調用這個函數判斷 if (isHidden(element)) { //判斷是否在界面上 return false; } var box = element.getBoundingClientRect(); //計算四邊的距離是否滿足條件 return (box.right >= view.l && box.bottom >= view.t && box.left <= view.r && box.top <= view.b); };
2.已經有了是否加載的判斷函數,那麽如何做到圖片的懶加載?
先加載loadding小菊花圖片,當滿足懶加載的條件時候,切換img的src屬性,
對於img元素的設置有兩個比較重要的值一個是src,一個是data-echo ,(還有一個是背景圖片,不太重要,忽略他)兩個,src設置小菊花的地址,data-echo真實的地址;
那麽所有頁面元素都這樣設置後,會有什麽影響?
當所有圖片都用設置src為同一值,也就是用同一張菊花圖,加載完之後就可以通用了
img這個元素的特性就是,當設置了src屬性,他會去先加載這張圖圖片,如果在js裏面馬上改變了img的src屬性,他會同事再進行一次網絡請求去加載你js設置的src地址的圖片
但是 會先將html裏面設置的src圖片加載完,顯示,你什麽時候加載完第二個圖片什麽時候替換,如果你在第二張圖片加載的時候又改變了src的值,,,那也是一樣的,什麽加載完什麽時候顯示,沒加載完的情況下顯示原來的
源代碼:
if (inView(elem, view)) {//是否滿足加載條件 if (unload) {//如果設置超出了不加載,保存小菊花地址在data-echo-placeholder屬性 elem.setAttribute(‘data-echo-placeholder‘, elem.src); } if (elem.getAttribute(‘data-echo-background‘) !== null) {//img的背景圖片 elem.style.backgroundImage = ‘url(‘ + elem.getAttribute(‘data-echo- background‘) + ‘)‘; } //當ele的src不等於data-echo的值,也就是真蒸的圖片地址,改變圖片的src else if (elem.src !== (src = elem.getAttribute(‘data-echo‘))) { elem.src = src; } if (!unload) { //如果沒有設置超出不加載,在這裏就可以清除這些屬性了 elem.removeAttribute(‘data-echo‘); elem.removeAttribute(‘data-echo-background‘); } callback(elem, ‘load‘); } else if (unload && !!(src = elem.getAttribute(‘data-echo-placeholder‘))) { //處理超出不加載圖片的情況,把原來保存的小菊花圖賦給elem的src //因為小菊花是最開始就加載好了的,所以圖片切換回小菊花,不再加載之前設置的真實圖片 if (elem.getAttribute(‘data-echo-background‘) !== null) { elem.style.backgroundImage = ‘url(‘ + src + ‘)‘; } else { elem.src = src; } elem.removeAttribute(‘data-echo-placeholder‘); callback(elem, ‘unload‘); } } if (!length) { echo.detach();//移除事件監聽 }
3,scroll函數節流
函數節流,兩種方式:
1:在滾動的時候不會觸發,滾動停下來才會隔一段時間觸發
2:每隔一段事件都觸發
//第一種方式,每次滾動過程中一直觸發,每次都會新清除上一次的setTimout,添加一個新的setTimout var poll; function throttle(){ clearTimeout(poll); poll=setTimeout(function(){ echo.render(); },delay||250) }
var poll;
function throttle(){ if(poll){ //存在setTimout,不清除,直接返回 return ; } clearTimout(poll); poll=setTimeout(function(){ echo.render(); poll=null; //允許再次添加定時器 },delay||250) }
圖片懶加載庫echo.js源碼學習