WEB性能优化--懒加载、预加载
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 插件实现懒加载
转载自:https://segmentfault.com/a/1190000041517694