知道什么是懒加载

说通俗点就是轮到我我再出现,而不是一进入页面就出现

为什么需要

  1. 节省资源
  2. 加快网页打开
  3. 提升用户体育
  4. 巴拉巴拉

懒加载原理

红色为我们实际看到的浏览器窗口,黑色的为实际网页的长度

我们刚进入主页的时候

用户拖动滚动条,看到绿色的框框,这些绿色的框框才开始加载出来

必要知道的知识

  1. 获取元素距离顶部(body)的距离:元素.offsetTop

    1. 注意:如果元素的父元素(不管是祖父还是曾祖父还是亲生父亲),只要任意一个父亲开启了定位(不管是相对还是绝对),那么子元素的offsetTop属性值都是参考父元素的
    2. 如果父元素没有开启定位,那么就参考body
    3. 元素.offsetLeft同理
  2. 获取浏览器垂直滚动的距离:document.documentElement.onscrollTop

  3. offsetTop和offsetLeft 这两个属性,IE 、Opera和Firefox对它俩的解释存在差异:

    1. IE5.0+ 、Opera8.0+: offsetTop和offsetLeft 都是相对父级元素
    2. Firefox1.06: offsetTop和offsetLeft 都是相对于body元素
  4. 为了解决父元素如果开启定位的问题,我们可以使用offsetParent加循环获取距离body的距离

    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
    //获取元素距离body的top值和left值
    function getPoint(obj) {
    //记录left的值
    var left = 0;
    //记录top的值
    var top = 0;
    //如果需要减去边框的距离,可以解除下面这二行注释
    //var borderLeftWidth;
    //var borderTopWidth;

    //如果obj.offsetParent获取不到父级了,就会跳出循环
    while (obj) {
    left = left + obj.offsetLeft;
    top = top + obj.offsetTop;
    //如果需要减去边框的距离,可以解除下面这二行注释,并将前二行注释
    //left = left + obj.offsetLeft - borderLeftWidth;
    //top = top + obj.offsetTop - borderTopWidth;
    obj = obj.offsetParent;
    }
    //返回距离body的left值和top值
    return {
    left,
    top
    };
    }

实现懒加载

  1. 一开始的思路(错误的):

    1. 先获取元素距离可视窗口顶部的距离,然后再和可视窗口的高度进行比较,如果小于可视窗口的高度,就加载出来(错误,因为二者距离都是死的)
  2. 后来的思路(正确的)

    1. 还是依旧获取元素距离可是窗口顶部的距离,然后再和(可视窗口的高度+滚动的距离)进行比较,如果某一个元素距离顶部距离小于这二者之和的距离,则元素里面的资源加载出来

    代码

    css代码
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    <style>
    * {
    margin: 0;
    padding: 0;
    }
    body,
    html {
    width: 100%;
    height: 100%;
    }
    img {
    vertical-align: bottom;
    display: inline;
    width: 590px;
    height: 500px;
    }
    .content {
    width: 1200px;
    margin: 0 auto;
    }
    </style>
    HTML代码
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    <div class="header">
    <h2>图片展示</h2>
    </div>
    <div class="content">
    <img data-src="./img/01.jpg" alt="">
    <img data-src="./img/02.jpg" alt="">
    <img data-src="./img/03.jpg" alt="">
    <img data-src="./img/04.jpg" alt="">
    <img data-src="./img/05.jpg" alt="">
    <img data-src="./img/06.jpg" alt="">
    <img data-src="./img/07.jpg" alt="">
    <img data-src="./img/08.jpg" alt="">
    <img data-src="./img/09.jpg" alt="">
    <img data-src="./img/10.jpg" alt="">
    <img data-src="./img/10.jpg" alt="">
    <img data-src="./img/11.jpg" alt="">
    <img data-src="./img/12.jpg" alt="">
    </div>
    JavaScript代码
    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
    <script>
    //获取元素距离body的top值和left值
    function getPoint(obj) {
    var left = 0;
    var top = 0;
    while (obj) {
    left = left + obj.offsetLeft;
    top = top + obj.offsetTop;
    obj = obj.offsetParent;
    }
    return {
    left,
    top
    };
    }
    //防止图片没有加载出来获取不到图片的offsetTop值,就填加了一个window.onload事件
    //页面初始化(用户刚刚进入页面的时候)
    window.onload = function () {
    var domHeight = document.documentElement.clientHeight; //视口的高度
    var imgs = document.querySelectorAll("img");
    //然后循环
    //每一个元素判断距离body的值是否 小于 (可视窗口的高度+垂直滚动的距离)
    for (var v of imgs) {
    if (getPoint(v).top < (domHeight + document.documentElement.scrollTop)) {
    //显示图片
    // v.src=v.dataset.src;也可以获取自定义属性值
    v.src = v.getAttribute("data-src");
    }
    }
    }
    //滚动事件
    window.onscroll = function () {
    var domHeight = document.documentElement.clientHeight; //视口的高度
    var imgs = document.querySelectorAll("img");
    //然后循环
    for (var v of imgs) {
    //每一个元素判断距离body的值是否 小于 (可视窗口的高度+垂直滚动的距离)
    if (getPoint(v).top < (domHeight + document.documentElement.scrollTop)) {
    //显示图片
    // v.src=v.dataset.src;
    v.src = v.getAttribute("data-src");
    }
    }
    }
    </script>

    展示效果

    可以看到图片不是一次性加载出来,而是随着滚动条滚动才加载出来的