189 8069 5689

基于纯JS如何实现多张图片的懒加载

小编给大家分享一下基于纯JS如何实现多张图片的懒加载,希望大家阅读完这篇文章之后都有所收获,下面让我们一起去探讨吧!

创新互联专业为企业提供临西网站建设、临西做网站、临西网站设计、临西网站制作等企业网站建设、网页设计与制作、临西企业网站模板建站服务,十载临西做网站经验,不只是建网站,更提供有价值的思路和整体网络服务。

一、效果图如下

基于纯JS如何实现多张图片的懒加载

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

1、还没加载图片的时候,默认显示加载图片背景图

2、刚开始进入页面,自动加载第一屏幕的图片

3、下拉界面,当一张图片容器完全显露出屏幕,即刻加载图片,替换背景图

4、加载图片的时候,有渐进显示图片效果

二、难点

1)如何Ajax请求数据

2)如何动态将json数据绑定到html中。

3)如何通过对图片的定位计算,触发图片懒加载机制

4)加分项,显示图片时有渐现的过渡动画

三、前期知识点

1)Ajax相关知识,XMLHttpRequest对象,所有现代的浏览器都支持此对象。

2)innerHTML,数据绑定使用字符串拼接的方式

3)HTML DOM getAttribute() 方法,返回自定属性名的属性值(主要是用于返回自定义属性的属性值)

4)图片的 onload事件,当图片的src属性的属性值为正确(即能成功加载图片),才能触发图片的onload事件

四、难点逐一攻破

1)如何Ajax请求数据

分四步走

// 1)首先创建一个Ajax对象
var xhr = new XMLHttpRequest;
// 2)打开我们需要请求的数据的那个文件地址
// URL地址后面加随机数目的:清除每一次请求数据时候(get请求)产生的缓存
// 因为每次访问的地址不一样,样浏览器就不会尝试缓存来自服务器的响应,读取本地缓存的数据。
xhr.open('get', 'json/newsList.txt?' + Math.random(), false); // false代表同步
 // 3)监听请求的状态
xhr.onreadystatechange = function () {
  if (xhr.readyState === 4 && /^2\d{2}$/.test(xhr.status)) {
    var val = xhr.responseText;
    jsonData = utils.jsonParse(val);
  }
}
// 4)发送请求
xhr.send(null);

2)如何动态将json数据绑定到html中。

字符串拼接的方式(数据绑定中最常用的方式),即通过使用innerHTML,对页面元素进行字符串拼接,再重新渲染到页面中

var str = "";
if (jsonData) {
  for (var i = 0, len = jsonData.length; i < len; i++) {
    var curData = jsonData[i];
    str += '
  • ';     str += '
    ';     str += '

    ' + curData["title"] + '

    ';     str += '

    ' + curData["desc"] + '

    ';     str += '
    ';     str += '
  • ';   }   news.innerHTML += str; }  

    优势:数据绑定最常用的方式,因为浏览器只需要渲染一次(所有模板引擎数据绑定的原理就是字符串拼接,vue、angular、jade、kTemplate.js等等)

    事先把内容拼接好,最后统一添加到页面中,只引发一次回流

    弊端:我们把新凭借的字符串添加到#ul1中,原有的三个li的鼠标滑过效果都消失了(原来标签绑定的事件都消失了)
    原来,oUl.innerHTML的作用是把原来的标签以字符串的方式取出,原来作为标签的时候,对应事件绑定的东西已经没有了,然后进行字符串拼接,

    但是,拼接完成之后,还是字符串!最后再把字符串统一添加到页面中,浏览器还需要把字符串渲染成为对应的标签

    3)如何通过对图片的定位计算,触发图片懒加载机制(最关键点)

    基于纯JS如何实现多张图片的懒加载

    思路:

    A:代表图片距离屏幕顶部的距离

    //这里使用了utils工具类中的offset方法,具体实现看下面源码
    var A = utils.offset(curImgPar).offsetTop + curImgPar.offsetHeight;

    B:代表一屏幕距离+滚动条滚动距离

    //这里使用了utils工具类中的win方法,具体实现看下面源码
    var B = utils.win("clientHeight") + utils.win("scrollTop");

    当A < B的时候,此时懒加载的默认图片才能完整显示出来,这个时候就需要触发图片懒加载

    4)加载图片的时候,有渐进显示图片效果

    思路,利用window.setInterval 方法,通过对当前图片的透明度属性(curImg.style.opacity) 从透明0开始到透明度1,变化总时间为500ms即可

    // ->实现渐现效果
    function fadeIn(curImg) {
      var duration = 500, // 总时间
      interval = 10, //10ms走一次
      target = 1; //总距离是1
      var step = (target / duration) * interval; //每一步的步长
      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

    
    
    
      
      
       
      多张图片的延迟加载
      
        * {
          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,中的第一个*/
          position: absolute;
          top: 10px;
          left: 0;
          width: 75px;
          height: 60px;
          background: url("./img/loading.PNG") no-repeat center center #e1e1e1;
          background-size: 100% 100%;
        }
        /*移动端布局,最外层容器是不设置宽高的*/
     
        .news li > div:first-child img {
          display: none;
          width: 100%;
          height: 100%;
          opacity: 0; /*这里设置为0的目的是,实现渐进的效果,后面的fadeIn函数,作用就是让图片透明都从0变成1*/
        }
     
        .news li > div:nth-child(2) {
          height: 60px;
          margin-left: 80px;
        }
        .news li > div:nth-child(2) h3 {
          height: 20px;
          line-height: 20px;
          /*实现文字超出一行自动裁切*/
          overflow: hidden;
          text-overflow: ellipsis; /*超出部分省略号显示*/
          white-space: nowrap; /*强制不换行*/
        }
        .news li > div:nth-child(2) p {
          line-height: 20px;
          font-size: 12px;
          color: #616161;
        }
      
    
    
      
        
          
            
          
          
            
            
          
        
      
     
     
     
     
    
    
      var news = document.getElementById("news"),
        imgList = news.getElementsByTagName("img");
     
      // 1、获取需要绑定的数据(通过Ajax)
      var jsonData = null;
      ~function () {
        // 1)首先创建一个Ajax对象
        var xhr = new XMLHttpRequest;
        // 2)打开我们需要请求的数据的那个文件地址
        // URL地址后面加随机数目的:清除每一次请求数据时候(get请求)产生的缓存
        // 因为每次访问的地址不一样,样浏览器就不会尝试缓存来自服务器的响应,读取本地缓存的数据。
        xhr.open('get', 'json/newsList.txt?' + Math.random(), false); // false代表同步
        // 3)监听请求的状态
        xhr.onreadystatechange = function () {
          if (xhr.readyState === 4 && /^2\d{2}$/.test(xhr.status)) {
            var val = xhr.responseText;
            jsonData = utils.jsonParse(val);
          }
        }
        // 4)发送请求
        xhr.send(null);
      }();
      console.log(jsonData);
     
      // 2、数据绑定(使用字符串拼接的方式)
      ~function () {
        var str = "";
        if (jsonData) {
          for (var i = 0, len = jsonData.length; i < len; i++) {
            var curData = jsonData[i];
            str += '
  • ';         str += '
    ';         str += '

    ' + curData["title"] + '

    ';         str += '

    ' + curData["desc"] + '

    ';         str += '
    ';         str += '
  • ';       }       news.innerHTML += str;     }   }();     // 3、图片延迟加载   // ->首先实现单张图片的延时加载   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;   }     // -> 循环处理每一张图片   function handleAllImg() {     for (var i = 0, len = imgList.length; i < len; i++) {       var curImg = imgList[i];       if (curImg.isLoad) { // 当前图片处理过的话,就不需重新进行处理         continue;       }         // ->只有当A小于B的时候再进行处理 //     var A = utils.offset(curImg).top + curImg.offsetHeight; // 这里A不能这么计算,因为此时图片是隐藏的,没有图片,他的offsetHeight当让也是为0                                    // 如果我要的到图片的A值,我们可以通过拿到他父节点的容器就行了,哈哈       var curImgPar = curImg.parentNode,         A = utils.offset(curImgPar).offsetTop + curImgPar.offsetHeight,         B = utils.win("clientHeight") + utils.win("scrollTop");       if (A < B) {         lazyImg(curImg);       }     }   }     // ->实现渐现效果   function fadeIn(curImg) {     var duration = 500, // 总时间       interval = 10, //10ms走一次       target = 1; //总距离是1     var step = (target / duration) * interval; //每一步的步长     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、开始的时候(过500ms)加载1屏幕的图片,当滚动条滚动的时候,加载其他图片   window.setTimeout(handleAllImg, 500);   window.onscroll = handleAllImg;    

    2)utils.js

    // 为了与全局变量冲突,我们使用单例模式
    var utils = {
     // jsonParse: 把JSON格式的字符串转化为JSON格式的对象
     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这个数字
           val = reg.test(val)?reg.exec(val)[1]/100:1 // 超厉害,test与exec一起使用!!!
         }
         val = curEle.currentStyle[attr];
       }
       reg = /^-?\d+(\.\d+)?(px|pt|rem|em)?$/i; //匹配的情况:纯数值或者带单位的数值
       return reg.test(val) ? parseFloat(val) : val;
     },
     
     offset : function(curEle) {
       var totalLeft = null,
         totalTop = null,
         par = curEle.offsetParent;
       // 首先把自己本身的进行累加
       totalLeft += curEle.offsetLeft;
       totalTop += curEle.offsetTop;
     
       while (par) {
         if (navigator.userAgent.indexOf("MSIE 8.0") === -1) {
           // 累加父级参照物边框
           totalTop += par.clientTop;
           totalLeft += par.clientLeft;
         }
         // 累加父级参照物本身的偏移
         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网络强国战略与“十三五”十四大战略", "desc": "1互联网是二十世纪人类最大的发明,互联网是二十世纪人类最大的发明"},
     {"img":"./img/new2.PNG", "title": "2网络强国战略与“十三五”十四大战略", "desc": "2互联网是二十世纪人类最大的发明,互联网是二十世纪人类最大的发明"},
     {"img":"./img/new3.PNG", "title": "3网络强国战略与“十三五”十四大战略", "desc": "3互联网是二十世纪人类最大的发明,互联网是二十世纪人类最大的发明"}
    ]

    看完了这篇文章,相信你对“基于纯JS如何实现多张图片的懒加载”有了一定的了解,如果想了解更多相关知识,欢迎关注创新互联行业资讯频道,感谢各位的阅读!


    名称栏目:基于纯JS如何实现多张图片的懒加载
    文章位置:http://cdxtjz.cn/article/pighdd.html

    其他资讯