小編給大家分享一下基于純JS如何實(shí)現(xiàn)多張圖片的懶加載,希望大家閱讀完這篇文章之后都有所收獲,下面讓我們一起去探討吧!
創(chuàng)新互聯(lián)專業(yè)為企業(yè)提供臨西網(wǎng)站建設(shè)、臨西做網(wǎng)站、臨西網(wǎng)站設(shè)計(jì)、臨西網(wǎng)站制作等企業(yè)網(wǎng)站建設(shè)、網(wǎng)頁設(shè)計(jì)與制作、臨西企業(yè)網(wǎng)站模板建站服務(wù),十載臨西做網(wǎng)站經(jīng)驗(yàn),不只是建網(wǎng)站,更提供有價(jià)值的思路和整體網(wǎng)絡(luò)服務(wù)。
一、效果圖如下
上面的效果圖,效果需求如下
1、還沒加載圖片的時(shí)候,默認(rèn)顯示加載圖片背景圖
2、剛開始進(jìn)入頁面,自動(dòng)加載第一屏幕的圖片
3、下拉界面,當(dāng)一張圖片容器完全顯露出屏幕,即刻加載圖片,替換背景圖
4、加載圖片的時(shí)候,有漸進(jìn)顯示圖片效果
二、難點(diǎn)
1)如何Ajax請(qǐng)求數(shù)據(jù)
2)如何動(dòng)態(tài)將json數(shù)據(jù)綁定到html中。
3)如何通過對(duì)圖片的定位計(jì)算,觸發(fā)圖片懶加載機(jī)制
4)加分項(xiàng),顯示圖片時(shí)有漸現(xiàn)的過渡動(dòng)畫
三、前期知識(shí)點(diǎn)
1)Ajax相關(guān)知識(shí),XMLHttpRequest對(duì)象,所有現(xiàn)代的瀏覽器都支持此對(duì)象。
2)innerHTML,數(shù)據(jù)綁定使用字符串拼接的方式
3)HTML DOM getAttribute() 方法,返回自定屬性名的屬性值(主要是用于返回自定義屬性的屬性值)
4)圖片的 onload事件,當(dāng)圖片的src屬性的屬性值為正確(即能成功加載圖片),才能觸發(fā)圖片的onload事件
四、難點(diǎn)逐一攻破
1)如何Ajax請(qǐng)求數(shù)據(jù)
分四步走
// 1)首先創(chuàng)建一個(gè)Ajax對(duì)象 var xhr = new XMLHttpRequest; // 2)打開我們需要請(qǐng)求的數(shù)據(jù)的那個(gè)文件地址 // URL地址后面加隨機(jī)數(shù)目的:清除每一次請(qǐng)求數(shù)據(jù)時(shí)候(get請(qǐng)求)產(chǎn)生的緩存 // 因?yàn)槊看卧L問的地址不一樣,樣瀏覽器就不會(huì)嘗試緩存來自服務(wù)器的響應(yīng),讀取本地緩存的數(shù)據(jù)。 xhr.open('get', 'json/newsList.txt?' + Math.random(), false); // false代表同步 // 3)監(jiān)聽請(qǐng)求的狀態(tài) xhr.onreadystatechange = function () { if (xhr.readyState === 4 && /^2\d{2}$/.test(xhr.status)) { var val = xhr.responseText; jsonData = utils.jsonParse(val); } } // 4)發(fā)送請(qǐng)求 xhr.send(null);
2)如何動(dòng)態(tài)將json數(shù)據(jù)綁定到html中。
字符串拼接的方式(數(shù)據(jù)綁定中最常用的方式),即通過使用innerHTML,對(duì)頁面元素進(jìn)行字符串拼接,再重新渲染到頁面中
var str = ""; if (jsonData) { for (var i = 0, len = jsonData.length; i < len; i++) { var curData = jsonData[i]; str += '
' + curData["desc"] + '
'; str += '優(yōu)勢(shì):數(shù)據(jù)綁定最常用的方式,因?yàn)闉g覽器只需要渲染一次(所有模板引擎數(shù)據(jù)綁定的原理就是字符串拼接,vue、angular、jade、kTemplate.js等等)
事先把內(nèi)容拼接好,最后統(tǒng)一添加到頁面中,只引發(fā)一次回流
弊端:我們把新憑借的字符串添加到#ul1中,原有的三個(gè)li的鼠標(biāo)滑過效果都消失了(原來標(biāo)簽綁定的事件都消失了)
原來,oUl.innerHTML的作用是把原來的標(biāo)簽以字符串的方式取出,原來作為標(biāo)簽的時(shí)候,對(duì)應(yīng)事件綁定的東西已經(jīng)沒有了,然后進(jìn)行字符串拼接,
但是,拼接完成之后,還是字符串!最后再把字符串統(tǒng)一添加到頁面中,瀏覽器還需要把字符串渲染成為對(duì)應(yīng)的標(biāo)簽
3)如何通過對(duì)圖片的定位計(jì)算,觸發(fā)圖片懶加載機(jī)制(最關(guān)鍵點(diǎn))
思路:
A:代表圖片距離屏幕頂部的距離
//這里使用了utils工具類中的offset方法,具體實(shí)現(xiàn)看下面源碼 var A = utils.offset(curImgPar).offsetTop + curImgPar.offsetHeight;
B:代表一屏幕距離+滾動(dòng)條滾動(dòng)距離
//這里使用了utils工具類中的win方法,具體實(shí)現(xiàn)看下面源碼 var B = utils.win("clientHeight") + utils.win("scrollTop");
當(dāng)A < B的時(shí)候,此時(shí)懶加載的默認(rèn)圖片才能完整顯示出來,這個(gè)時(shí)候就需要觸發(fā)圖片懶加載
4)加載圖片的時(shí)候,有漸進(jìn)顯示圖片效果
思路,利用window.setInterval 方法,通過對(duì)當(dāng)前圖片的透明度屬性(curImg.style.opacity) 從透明0開始到透明度1,變化總時(shí)間為500ms即可
// ->實(shí)現(xiàn)漸現(xiàn)效果 function fadeIn(curImg) { var duration = 500, // 總時(shí)間 interval = 10, //10ms走一次 target = 1; //總距離是1 var step = (target / duration) * interval; //每一步的步長(zhǎng) var timer = window.setInterval(function () { var curOp = utils.getCss2SS(curImg, "opacity"); if (curOp >= 1) { curImg.style.opacity = 1; window.clearInterval(timer); return } curOp += step; curImg.style.opacity = curOp; }, interval); }
五、完整代碼
1)main.html
多張圖片的延遲加載
2)utils.js
// 為了與全局變量沖突,我們使用單例模式 var utils = { // jsonParse: 把JSON格式的字符串轉(zhuǎn)化為JSON格式的對(duì)象 jsonParse: function (str) { var val = null; try { val = JSON.parse(str); } catch (e) { val = eval('(' + str + ')'); } return val; }, getCss2SS : function(curEle, attr) { var val = null, reg = null; if ('getComputedStyle' in window) { val = window.getComputedStyle(curEle, null)[attr]; } else { if (attr === 'opacity') { val = curEle.currentStyle[attr]; // ->返回 alpha(opacity=10) reg = /^alpha\(opacity=(\d+(?:\.\d+)?)\)$/i; // 獲取10這個(gè)數(shù)字 val = reg.test(val)?reg.exec(val)[1]/100:1 // 超厲害,test與exec一起使用?。?! } val = curEle.currentStyle[attr]; } reg = /^-?\d+(\.\d+)?(px|pt|rem|em)?$/i; //匹配的情況:純數(shù)值或者帶單位的數(shù)值 return reg.test(val) ? parseFloat(val) : val; }, offset : function(curEle) { var totalLeft = null, totalTop = null, par = curEle.offsetParent; // 首先把自己本身的進(jìn)行累加 totalLeft += curEle.offsetLeft; totalTop += curEle.offsetTop; while (par) { if (navigator.userAgent.indexOf("MSIE 8.0") === -1) { // 累加父級(jí)參照物邊框 totalTop += par.clientTop; totalLeft += par.clientLeft; } // 累加父級(jí)參照物本身的偏移 totalTop += par.offsetTop; totalLeft += par.offsetLeft; par = par.offsetParent; } console.log('offsetTop: ' + totalTop + ', offsetLeft: ' + totalLeft); var result = {}; result.offsetTop = totalTop; result.offsetLeft = totalLeft; return result; }, win : function(attr, value) { if (value === undefined) { return document.documentElement[attr] || document.body[attr]; } document.documentElement[attr] = value; document.body[attr] = value; } };
3、json文件
[{"img":"./img/new1.PNG", "title": "1網(wǎng)絡(luò)強(qiáng)國戰(zhàn)略與“十三五”十四大戰(zhàn)略", "desc": "1互聯(lián)網(wǎng)是二十世紀(jì)人類最大的發(fā)明,互聯(lián)網(wǎng)是二十世紀(jì)人類最大的發(fā)明"}, {"img":"./img/new2.PNG", "title": "2網(wǎng)絡(luò)強(qiáng)國戰(zhàn)略與“十三五”十四大戰(zhàn)略", "desc": "2互聯(lián)網(wǎng)是二十世紀(jì)人類最大的發(fā)明,互聯(lián)網(wǎng)是二十世紀(jì)人類最大的發(fā)明"}, {"img":"./img/new3.PNG", "title": "3網(wǎng)絡(luò)強(qiáng)國戰(zhàn)略與“十三五”十四大戰(zhàn)略", "desc": "3互聯(lián)網(wǎng)是二十世紀(jì)人類最大的發(fā)明,互聯(lián)網(wǎng)是二十世紀(jì)人類最大的發(fā)明"} ]
看完了這篇文章,相信你對(duì)“基于純JS如何實(shí)現(xiàn)多張圖片的懶加載”有了一定的了解,如果想了解更多相關(guān)知識(shí),歡迎關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道,感謝各位的閱讀!