最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

基于純JS實(shí)現(xiàn)多張圖片的懶加載Lazy過程解析

 更新時(shí)間:2019年10月14日 08:25:03   作者:彭勝光  
這篇文章主要介紹了基于純JS實(shí)現(xiàn)多張圖片的懶加載Lazy過程解析,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下

一、效果圖如下

上面的效果圖,效果需求如下

1、還沒加載圖片的時(shí)候,默認(rèn)顯示加載圖片背景圖

2、剛開始進(jìn)入頁(yè)面,自動(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ì)嘗試緩存來(lái)自服務(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ì)頁(yè)面元素進(jìn)行字符串拼接,再重新渲染到頁(yè)面中

var str = "";
if (jsonData) {
  for (var i = 0, len = jsonData.length; i < len; i++) {
    var curData = jsonData[i];
    str += '<li>';
    str += '<div><img src="" trueImg="' + curData["img"] + '"></div>';
    str += '<div><h2>' + curData["title"] + '</h2>';
    str += '<p>' + curData["desc"] + '</p>';
    str += '</div>';
    str += '</li></div>';
  }
  news.innerHTML += str;
} <strong> </strong>

優(yōu)勢(shì):數(shù)據(jù)綁定最常用的方式,因?yàn)闉g覽器只需要渲染一次(所有模板引擎數(shù)據(jù)綁定的原理就是字符串拼接,vue、angular、jade、kTemplate.js等等)

事先把內(nèi)容拼接好,最后統(tǒng)一添加到頁(yè)面中,只引發(fā)一次回流

弊端:我們把新憑借的字符串添加到#ul1中,原有的三個(gè)li的鼠標(biāo)滑過效果都消失了(原來(lái)標(biāo)簽綁定的事件都消失了)
原來(lái),oUl.innerHTML的作用是把原來(lái)的標(biāo)簽以字符串的方式取出,原來(lái)作為標(biāo)簽的時(shí)候,對(duì)應(yīng)事件綁定的東西已經(jīng)沒有了,然后進(jìn)行字符串拼接,

但是,拼接完成之后,還是字符串!最后再把字符串統(tǒng)一添加到頁(yè)面中,瀏覽器還需要把字符串渲染成為對(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)圖片才能完整顯示出來(lái),這個(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

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <!--做移動(dòng)端響應(yīng)式布局頁(yè)面,都需要加下面的meta-->
  <meta name="viewport" content="width=device-width, initial-scale=1.0"> <!--meta:vp+tap一鍵生成-->
  <title>多張圖片的延遲加載</title>
  <style type="text/css">
    * {
      margin: 0;
      padding: 0;
      font-family: "Microsoft Sans Serif";
      font-size: 14px;
    }
    ul, li {
      list-style: none;
    }
    img {
      display: block;
      border: none;
    }
    .news {
      padding: 10px;
    }
    .news li {
      position: relative;
      height: 60px;
      padding: 10px 0;
      border-bottom: 1px solid #eee;
    }
    .news li > div:first-child {  /*意思是,li下面的子div,中的第一個(gè)*/
      position: absolute;
      top: 10px;
      left: 0;
      width: 75px;
      height: 60px;
      background: url("./img/loading.PNG") no-repeat center center #e1e1e1;
      background-size: 100% 100%;
    }
    /*移動(dòng)端布局,最外層容器是不設(shè)置寬高的*/
 
    .news li > div:first-child img {
      display: none;
      width: 100%;
      height: 100%;
      opacity: 0; /*這里設(shè)置為0的目的是,實(shí)現(xiàn)漸進(jìn)的效果,后面的fadeIn函數(shù),作用就是讓圖片透明都從0變成1*/
    }
 
    .news li > div:nth-child(2) {
      height: 60px;
      margin-left: 80px;
    }
    .news li > div:nth-child(2) h2 {
      height: 20px;
      line-height: 20px;
      /*實(shí)現(xiàn)文字超出一行自動(dòng)裁切*/
      overflow: hidden;
      text-overflow: ellipsis; /*超出部分省略號(hào)顯示*/
      white-space: nowrap; /*強(qiáng)制不換行*/
    }
    .news li > div:nth-child(2) p {
      line-height: 20px;
      font-size: 12px;
      color: #616161;
    }
  </style>
</head>
<body>
  <ul id="news" class="news">
    <!--<li>-->
      <!--<div>-->
        <!--<img src="./img/new1.PNG" alt="">-->
      <!--</div>-->
      <!--<div>-->
        <!--<h2>香港四大家族往事,香港四大家族往事,香港四大家族往事</h2>-->
        <!--<p>香港四大家族往事:李嘉誠(chéng)為鄭裕彤扶靈香港四大家族往事:李嘉誠(chéng)為鄭裕彤扶靈</p>-->
      <!--</div>-->
    <!--</li>-->
  </ul>
 
 
 
 
<script type="text/javascript" src="./tool/utils.js"></script>
<script type="text/javascript">
  var news = document.getElementById("news"),
    imgList = news.getElementsByTagName("img");
 
  // 1、獲取需要綁定的數(shù)據(jù)(通過Ajax)
  var jsonData = null;
  ~function () {
    // 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ì)嘗試緩存來(lái)自服務(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);
  }();
  console.log(jsonData);
 
  // 2、數(shù)據(jù)綁定(使用字符串拼接的方式)
  ~function () {
    var str = "";
    if (jsonData) {
      for (var i = 0, len = jsonData.length; i < len; i++) {
        var curData = jsonData[i];
        str += '<li>';
        str += '<div><img src="" trueImg="' + curData["img"] + '"></div>';
        str += '<div><h2>' + curData["title"] + '</h2>';
        str += '<p>' + curData["desc"] + '</p>';
        str += '</div>';
        str += '</li></div>';
      }
      news.innerHTML += str;
    }
  }();
 
  // 3、圖片延遲加載
  // ->首先實(shí)現(xiàn)單張圖片的延時(shí)加載
  function lazyImg(curImg) {
    var oImg = new Image;
    oImg.src = curImg.getAttribute("trueImg");
    oImg.onload = function() {
      curImg.src = this.src;
      curImg.style.display = "block";
      fadeIn(curImg);
      oImg = null;
    }
    curImg.isLoad = true;
  }
 
  // -> 循環(huán)處理每一張圖片
  function handleAllImg() {
    for (var i = 0, len = imgList.length; i < len; i++) {
      var curImg = imgList[i];
      if (curImg.isLoad) { // 當(dāng)前圖片處理過的話,就不需重新進(jìn)行處理
        continue;
      }
 
      // ->只有當(dāng)A小于B的時(shí)候再進(jìn)行處理
//     var A = utils.offset(curImg).top + curImg.offsetHeight; // 這里A不能這么計(jì)算,因?yàn)榇藭r(shí)圖片是隱藏的,沒有圖片,他的offsetHeight當(dāng)讓也是為0
                                   // 如果我要的到圖片的A值,我們可以通過拿到他父節(jié)點(diǎn)的容器就行了,哈哈
      var curImgPar = curImg.parentNode,
        A = utils.offset(curImgPar).offsetTop + curImgPar.offsetHeight,
        B = utils.win("clientHeight") + utils.win("scrollTop");
      if (A < B) {
        lazyImg(curImg);
      }
    }
  }
 
  // ->實(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);
  }
 
  // 4、開始的時(shí)候(過500ms)加載1屏幕的圖片,當(dāng)滾動(dòng)條滾動(dòng)的時(shí)候,加載其他圖片
  window.setTimeout(handleAllImg, 500);
  window.onscroll = handleAllImg;
   
</script>
</body>
</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)國(guó)戰(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)國(guó)戰(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)國(guó)戰(zhàn)略與“十三五”十四大戰(zhàn)略", "desc": "3互聯(lián)網(wǎng)是二十世紀(jì)人類最大的發(fā)明,互聯(lián)網(wǎng)是二十世紀(jì)人類最大的發(fā)明"}
]

以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • 微信小程序js文件改變參數(shù)并在視圖上及時(shí)更新【推薦】

    微信小程序js文件改變參數(shù)并在視圖上及時(shí)更新【推薦】

    這篇文章主要介紹了微信小程序js文件改變參數(shù)并在視圖上及時(shí)更新的實(shí)現(xiàn)代碼,本文給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友參考下吧
    2018-06-06
  • 網(wǎng)頁(yè)加載速度優(yōu)化技巧的方案詳解

    網(wǎng)頁(yè)加載速度優(yōu)化技巧的方案詳解

    這篇文章主要為大家介紹了網(wǎng)頁(yè)加載速度優(yōu)化技巧的方案詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪<BR>
    2023-05-05
  • JavaScript實(shí)現(xiàn)16進(jìn)制顏色值轉(zhuǎn)RGB的方法

    JavaScript實(shí)現(xiàn)16進(jìn)制顏色值轉(zhuǎn)RGB的方法

    這篇文章主要介紹了JavaScript實(shí)現(xiàn)16進(jìn)制顏色值轉(zhuǎn)RGB的方法,是javascript比較典型的數(shù)值轉(zhuǎn)換應(yīng)用技巧,非常具有實(shí)用價(jià)值,需要的朋友可以參考下
    2015-02-02
  • bootstrap自定義樣式之bootstrap實(shí)現(xiàn)側(cè)邊導(dǎo)航欄功能

    bootstrap自定義樣式之bootstrap實(shí)現(xiàn)側(cè)邊導(dǎo)航欄功能

    bootstrap自帶的響應(yīng)式導(dǎo)航欄是向下滑動(dòng)的,有時(shí)滿足不了個(gè)性化的需求,需要做一個(gè)類似于android drawerLayout 側(cè)滑的菜單,這就是我要實(shí)現(xiàn)的bootstrap自定義側(cè)滑菜單。接下來(lái)通過本文給大家介紹bootstrap實(shí)現(xiàn)側(cè)邊導(dǎo)航欄功能,感興趣的朋友一起看看吧
    2018-09-09
  • 深入理解JavaScript 解構(gòu)賦值

    深入理解JavaScript 解構(gòu)賦值

    JavaScript的解構(gòu)賦值是ES6引入的語(yǔ)法,允許以簡(jiǎn)潔的方式從數(shù)組或?qū)ο笾刑崛?shù)據(jù)并賦值給變量,包括數(shù)組解構(gòu)、對(duì)象解構(gòu)、參數(shù)解構(gòu)、變量交換等,它可以大幅簡(jiǎn)化代碼,提高開發(fā)效率,下面就一起來(lái)了解一下
    2024-09-09
  • Bootstrap每天必學(xué)之輪播(Carousel)插件

    Bootstrap每天必學(xué)之輪播(Carousel)插件

    Bootstrap每天必須之輪播(Carousel)插件,Bootstrap 輪播(Carousel)插件是一種靈活的響應(yīng)式的向站點(diǎn)添加滑塊的方式,感興趣的小伙伴們可以參考一下
    2016-04-04
  • uniapp自定義下拉刷新組件項(xiàng)目實(shí)踐總結(jié)分析

    uniapp自定義下拉刷新組件項(xiàng)目實(shí)踐總結(jié)分析

    在日常的開發(fā)過程中,我們經(jīng)常遇到下拉刷新的場(chǎng)景,很方便的刷新游覽的內(nèi)容,在此實(shí)現(xiàn)了一個(gè)下拉刷新的自定義組件,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步
    2023-09-09
  • 實(shí)現(xiàn)在?Chrome?中執(zhí)行?JavaScript?代碼

    實(shí)現(xiàn)在?Chrome?中執(zhí)行?JavaScript?代碼

    這篇文章主要介紹了實(shí)現(xiàn)在?Chrome?中執(zhí)行?JavaScript?代碼,下面來(lái)介紹如何在?Chrome?中打開開發(fā)者工具,以及如何在開發(fā)者工具中運(yùn)行調(diào)試?JavaScript?代碼,具有一的的參考價(jià)值,需要的朋友可以參考一下
    2022-03-03
  • bootstrap輪播圖示例代碼分享

    bootstrap輪播圖示例代碼分享

    這篇文章主要為大家詳細(xì)介紹了bootstrap輪播圖示例代碼,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-05-05
  • 支付寶小程序從手動(dòng)埋點(diǎn)到自動(dòng)埋點(diǎn)的實(shí)現(xiàn)過程

    支付寶小程序從手動(dòng)埋點(diǎn)到自動(dòng)埋點(diǎn)的實(shí)現(xiàn)過程

    埋點(diǎn)的意思是在你想要的數(shù)據(jù)節(jié)點(diǎn)出進(jìn)行設(shè)置,可以方便進(jìn)行采集,下面這篇文章主要給大家介紹了關(guān)于支付寶小程序從手動(dòng)埋點(diǎn)到自動(dòng)埋點(diǎn)的相關(guān)資料,需要的朋友可以參考下
    2022-03-03

最新評(píng)論

长治市| 凤冈县| 浙江省| 兴文县| 深水埗区| 克什克腾旗| 广安市| 渑池县| 台前县| 大洼县| 泾源县| 常德市| 黎川县| 普兰店市| 视频| 大名县| 黑水县| 枞阳县| 顺义区| 鄂托克旗| 昭通市| 丰顺县| 南城县| 宁海县| 朔州市| 台山市| 军事| 武穴市| 大厂| 十堰市| 浙江省| 资兴市| 弥渡县| 德清县| 盐池县| 齐齐哈尔市| 岳普湖县| 南昌市| 平舆县| 盐津县| 和政县|