一张图片引发的思考---懒加载

最近在做一个图片list预览组件,在一组图片list 中点击其中一张图片 可以放大 缩小,旋转、下载等功能。 但是list 中可能很多图片,如果首次打开这个页面, 每个图片都加载,浪费服务器资源,也给页面渲染带来极大的性能损耗。(http请求是宝贵的);
一.如何做到懒加载 也叫按需加载?
懒加载原理 ,初始化时候给页面的img 标签的src属性 ,默认赋值loading图片,增加一个 自定义的data-src 属性 ,存放真实的图片地址,遍历判断img 标签在视口中 , 把data-src 中的真实地址,赋值给src属性 ,加载真实的图片。
二.如何判断img 标签已经在视口
原始的转化方式 :
1. document.documentElement.clientHeight获取屏幕可视窗口高度 ,
2.el.offsetTop 获取元素距离文档顶部的 距离,
3.document.documentElement.scrollTop 文档向下滚动的距离。 如下图 当 ② - ① < ③    说明图片已经在视口内部。可以加载。
一张图片引发的思考---懒加载_第1张图片
现成的API    getBoundingClientRect  :
浏览器提供 Element.getBoundingClientRect() 方法来获取元素的大小以及位置,包括 矩形 盒子的大小,top 、left、bottom  right 。
如下图。这些位置信息是相对视口 左上角为原点返回的数值。什么情况下是img 进入视口的呢?  假设,我们获取img 相对视口的信息 const  coordinateData= el.getBoundingClientRect() ,  const clientHeight = window.innerHeight , 很容易 coordinateData.top ===clientHeight 的 时候 ,img 将要进入视口。ok 
一张图片引发的思考---懒加载_第2张图片

function isInViewport(el){
try{
   const {top,left}= el.getBoundingClientRect();
  const height= window.innerHeight;
  const width = window.innerWidth;
 return top<=height&& left<= width;
}catch(err){}
}

function getImgs(){
const imgs=  document.querySelectorAll('.photolist') ;
 Array.from(imgs).forEach(item=>{
    if (isInViewport(item)){
     if (item['data-isLoaded'])return;
     item.src = item['data-src'];
     item['data-isLoaded'] = true;
     }
})
}

上面的 代码 还为已经加载的img 标签添加了自定义属性,  如果该标签已经加载过图片, 以后的遍历就不会重新加载。
这里还可以优化下, 在页面滚动的时候 ,一直去访问dom 执行操作,对页面性能是很大的损耗。 这里我们可以写一个节流函数,
具体解释看这里;


function throttle(fn,delay){
   let deferTimer , last;
    return function (args){
      const context = this;
      const now = new Date();
      const _args = arguments;
   if(last&&now{
       fn.apply(context,_args);
       last=now;
      clearTimeout(deferTimer)
     },last+delay-now);
   }
} else {
    fn.apply(context,_args);
    last=now;

}
    }

}

window.addEventListener('scroll',()=>{
throttle(getImgs(),500ms)
});
 

你可能感兴趣的:(js)