前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >懒加载的实现原理

懒加载的实现原理

作者头像
挥刀北上
发布2019-07-19 15:40:36
1.3K0
发布2019-07-19 15:40:36
举报
文章被收录于专栏:Node.js开发

前端工程师在做页面优化的时候,如果页面中是类似图片列表的结构,会考虑使用懒加载(Lazy-Load)技术来优化页面的加载速度,今天就带大家来探究一下懒加载的原理。

首先我们实现页面布局,代码如下:

代码语言:javascript
复制
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
    <style>
    *{
            margin: 0;
            padding: 0;
        }
    .out{
        position: relative;
    }
    .inner{
        width: 300px;
        list-style: none;
        margin: 0 auto;
    }
li{
    width:300px;
    height: 300px;
    margin-top: 10px;
    overflow: hidden;
}
img{background: url("./image/t.gif");width: 100%;height: 100%;background-size: cover}
</style>
</head>
<body>
<div class="out">
    <ul class="inner">
        <li><img datasrc="./image/1.jpg" alt=""></li>
        <li><img datasrc="./image/2.jpg" alt=""></li>
        <li><img datasrc="./image/3.jpg" alt=""></li>
        <li><img datasrc="./image/4.jpg" alt=""></li>
        <li><img datasrc="./image/5.jpg" alt=""></li>
        <li><img datasrc="./image/5.jpg" alt=""></li>
        <li><img datasrc="./image/6.jpg" alt=""></li>
        <li><img datasrc="./image/7.jpg" alt=""></li>
        <li><img datasrc="./image/8.jpg" alt=""></li>
        <li><img datasrc="./image/9.jpg" alt=""></li>
        <li><img datasrc="./image/10.jpg" alt=""></li>
        <li><img datasrc="./image/11.jpg" alt=""></li>
        <li><img datasrc="./image/12.jpg" alt=""></li>
        <li><img datasrc="./image/13.jpg" alt=""></li>
        <li><img datasrc="./image/14.jpg" alt=""></li>
        <li><img datasrc="./image/15.jpg" alt=""></li>
        <li><img datasrc="./image/15.jpg" alt=""></li>
        <li><img datasrc="./image/16.jpg" alt=""></li>
        <li><img datasrc="./image/17.jpg" alt=""></li>
        <li><img datasrc="./image/18.jpg" alt=""></li>
        <li><img datasrc="./image/19.jpg" alt=""></li>
        <li><img datasrc="./image/20.jpg" alt=""></li>
        <li><img datasrc="./image/21.jpg" alt=""></li>
        <li><img datasrc="./image/22.jpg" alt=""></li>
        <li><img datasrc="./image/23.jpg" alt=""></li>
    </ul>
</div>
<script>
</script>
</body>
</html>

观察上面代码,我们发现img的src属性不存在,反而存在一个datasrc属性,datasrc属性中存储的反而是图片的真是地址。

这里我们用了一个img的背景图设置图片的默认显示图片,页面显示如下:

接下来就是实现图片懒加载的功能了,如何做呢?可以看到默认情况下图片显示的是gif图,用户拖动滚动框,当图片出现在浏览器的可视区域后,我们将图片的src值设置为datasrc,这样的话图片就实现了懒加载功能。

梳理上面的功能,我们发现:

1、我们需要监听网页的scroll事件

2、我们需要判断图片是否出现在浏览器的可视区域。

第一步可以轻松实现,但是第二步,如何判断图片出现在了可视区域呢?

首先我们可以用window.innerHeight或者document.documentElement.clientHeight来获取浏览器可视区域的高度,screenheight。

然后我们可以通过图片的getBoundingClientRect() 方法来获取返回元素的大小及其相对于视口的位置。对此 MDN 给出了非常清晰的解释:

该方法的返回值是一个 DOMRect 对象,这个对象是由该元素的 getClientRects() 方法返回的一组矩形的集合, 即:是与该元素相关的 CSS 边框集合 。 DOMRect 对象包含了一组用于描述边框的只读属性——left、top、right 和 bottom,单位为像素。除了 width 和 height 外的属性都是相对于视口的左上角位置而言的。 mdn

其中需要引起我们注意的就是 left、top、right 和 bottom,它们对应到元素上是这样的:

我们只需要获取可视区域的高度screen与img.getBoundingClientRect().top的差值是否大于等于0,就可以判断出图片是否出现在了可视区域内。

js脚本代码如下:

代码语言:javascript
复制
<script>
var screenHeight = window.innerHeight||document.documentElement.clientHeight;
var count = 0;
var img = document.querySelectorAll('.inner img');

function show(){
    for(var i=count;i<img.length;i++){
        console.log(i);
        var top  = img[i].getBoundingClientRect().top;
        if(screenHeight-top >= 0){
            img[i].src = img[i].getAttribute('datasrc')
            count++;
        }
    }
}
 show();
document.onscroll = show
</script>

仔细观察代码逻辑,每次触发滚动事件,都会计算可视区域顶部每张图片距离可视区域顶部的差值,如果大于0;说明图片出现在可视区域,将图片的src设置为图片的真实地址,这里需要注意的是页面初始加载进来时是不会滚动的,所以我们要主动执行一下show方法。

这里需要注意的是,我们设置了一个count变量,每次图片显示,将count递增,再次检测图片时从count开始检测,防止重复检测。

到此为止我们完成了图片懒加载额功能,下面是优化的代码,上面的scroll事件触发频率太高了,上篇文章,我们介绍了防抖,我们将其用在这个案例上,优化代码如下:

代码语言:javascript
复制
<script>
var screenHeight = window.innerHeight||document.documentElement.clientHeight;
var count = 0;
var img = document.querySelectorAll('.inner img');

function show(){
    for(var i=count;i<img.length;i++){
        console.log(i);
        var top  = img[i].getBoundingClientRect().top;
        if(screenHeight-top >= 0){
            img[i].src = img[i].getAttribute('datasrc')
            count++;
        }
    }
}
//  扩展防抖方法debounce
function debounce(cb){
    var timer = null;
    return function(e){
        console.log(111)
        var context = this;
        var event = e;
        if(timer){
            clearTimeout(timer);
            timer  = setTimeout(function(){
                cb.call(context,event)
            },600)
        }else{
            
            timer  = setTimeout(function(){
                cb.call(context,event)
            },600)
        }
    }
}
document.onscroll = debounce(show);
show();
</script>
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2019-03-21,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 nodejs全栈开发 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档