WEB性能优化--图片媒体篇
目标为了晋升客户端成果体验。
原生js实现(懒加载)
- 原理:图片的getBoundingClientRect().top高度 是否小于以后可视视图高度,小于则把data-src的url替换给src
1、第一种办法:获取对应元素举例顶部的间隔来判断。
// onload是等所有的资源文件加载结束当前再绑定事件window.onload = function(){ // 获取图片列表,即img标签列表 var imgs = document.querySelectorAll('img'); // 获取到浏览器顶部的间隔 function getTop(e){ return e.getBoundingClientRect().top; } // 懒加载实现 function lazyload(imgs){ // 可视区域高度 var h = window.innerHeight; //滚动区域高度 for(var i=0;i<imgs.length;i++){ //图片间隔顶部的间隔大于可视区域和滚动区域之和时懒加载 if (h>getTop(imgs[i])) { // 真实情况是页面开始有2秒空白,所以应用setTimeout定时2s (function(i){ setTimeout(function(){ // 不加立刻执行函数i会等于9 // 隐形加载图片或其余资源, //创立一个长期图片,这个图片在内存中不会到页面下来。实现隐形加载 var temp = new Image(); temp.src = imgs[i].getAttribute('data-src');//只会申请一次 // onload判断图片加载结束,真是图片加载结束,再赋值给dom节点 temp.onload = function(){ // 获取自定义属性data-src,用真图片替换假图片 imgs[i].src = imgs[i].getAttribute('data-src') } },2000) })(i) } } } lazyload(imgs); // 滚屏函数 window.onscroll =function(){ lazyload(imgs); }}
2、第二种办法:利用intersectionObserver-api监听元素是否进入到可视区域(较第一种办法更简略)
// 利用es6写法 const imgsBox = [...document.querySelectorAll('img')]; function lazyload(){ for(let i = 0;i<imgsBox.length;i++){ const imgsTarget = imgsBox[I]; if(isVisable(imgsTarget)){ imgsTarget.src = imgsTarget.dataset.src; imgsTarget.splice(i,1);//取得图片后出数组 i--; } } } //判断图片是否再可视化区域 function isVisable(imgsTarget){ let targetRect = imgsTarget.getBoundingClientRect(); return targetRect.bottom >0 && targetRect.top < window.innerHeight && targetRect.right >0 && targetRect.left < window.innerWight; } lazyload(); window.onscroll = function(){ lazyload(); } //onscroll也能够写成 window.addEventListener('scroll',lazyload,false); //false 示意冒泡
上诉办法因为scroll是高频发事件,所以用的时候最好应用节流函数。
function throttle(fn,wait,context){ var timer = null; return function(...args){ var context = context || this; var args = arguments; if(!timer){ timer = setTimeout(function(){ fn.apply(context,args); timer = null; },wait) } }} window.addEventListener('scroll',throttle(lazyload,250),false);
原生js(图片预加载)
- 提前加载下一张图片,基于promise实现
<img id='imgbox' /> const imgs = [ ]; //用来寄存图片src的数组,理论状况是去后盾取的值 const imgBox = document.getElementById('imgbox'); //取到寄存src的图片盒子,通过预加载替换src //这里用点击图片替换图片来实现预加载 let i = 0; //用来取数组图片src imgBox.addEventListener('click', ()=>{ if(i < imgs.length){ imgBox.src = imgs[i]; i++; if(i< imgs.length){ preLoad(imgs[i]).then(data=>{ //这个data就是咱们 return 的promise对象,传入imgs[i]的 }); } }else{ //此时是数组最初一张图片 } },false) function preLoad(src){ return new Promise(reslove,reject)=>{ const imgBox = document.getElementById('imgbox'); imgBox.src = src; imgBox.addEventerListener('load',()=>{reslove(imgBox)}); imgBox.addEventerListener('error',()=>{reject()}); } }
借鉴学习:https://juejin.cn/post/703445...
巧用lazysizes.js 插件实现懒加载
- 这个插件应用益处介于高频发、无论元素是否ajax实现,lazysizes都能够拾取到。
- 下载lazysizes.min.js 脚本。(或通过 npm:npm install lazysizes --save或 bower装置bower install lazysizes --save)
- 应用办法: 官网应用例子
- 官网文档:github