【JavaScript】前端性能优化-图片懒加载(附源码)

一、效果图如下 上面的效果图,效果需求如下 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 2 3 4 5 6 7 8 9 10 11 12 13 14 15 // 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,对页面元素进行字符串拼接,再重新渲染到页面中 1 2 3 4 5 6 7 8 9 10 11 12 13 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)如何通过对图片的定位计算,触发图片懒加载机制(最关键点) 思路: A:代表图片距离屏幕顶部的距离 1 2 //这里使用了utils工具类中的offset方法,具体实现看下面源码 var A = utils.offset(curImgPar).offsetTop + curImgPar.offsetHeight; B:代表一屏幕距离+滚动条滚动距离 1 2 //这里使用了utils工具类中的win方法,具体实现看下面源码 var B = utils.win("clientHeight") + utils.win("scrollTop"); 当A < B的时候,此时懒加载的默认图片才能完整显示出来,这个时候就需要触发图片懒加载 4)加载图片的时候,有渐进显示图片效果 思路,利用window.setInterval 方法,通过对当前图片的透明度属性(curImg.style.opacity) 从透明0开始到透明度1,变化总时间为500ms即可 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 // ->实现渐现效果 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); }   五、完整代码 实现懒加载只需要下面3个文件即可,需要请自行拷贝 1)main.html 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 多张图片的延迟加载
       2)utils.js 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 // 为了与全局变量冲突,我们使用单例模式 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文件 1 2 3 4 [{"img":"./img/new1.PNG", "title": "1网络强国战略与“十三五”十四大战略", "desc": "1互联网是二十世纪人类最大的发明,互联网是二十世纪人类最大的发明"}, {"img":"./img/new2.PNG", "title": "2网络强国战略与“十三五”十四大战略", "desc": "2互联网是二十世纪人类最大的发明,互联网是二十世纪人类最大的发明"}, {"img":"./img/new3.PNG", "title": "3网络强国战略与“十三五”十四大战略", "desc": "3互联网是二十世纪人类最大的发明,互联网是二十世纪人类最大的发明"} ] 不安逸,不浮躁,牛B就是一个学习累积的过程 分类: 《JavaScript高级程序设计》学习笔记 标签: 懒加载、滚动加载 好文要顶 关注我 收藏该文 彭胜光 关注 - 3 粉丝 - 22 +加关注 3 0 « 上一篇: 【JavaScript】深入理解call,以及与apply、bind的区别 posted @ 2019-10-14 00:07 彭胜光 阅读(327) 评论(0) 编辑 收藏 https://www.cnblogs.com/pengshengguang/p/11669176.html
    50000+
    5万行代码练就真实本领
    17年
    创办于2008年老牌培训机构
    1000+
    合作企业
    98%
    就业率

    联系我们

    电话咨询

    0532-85025005

    扫码添加微信