懒加载的原理和实现

·  阅读 415

1.懒加载概念

对于页面有很多静态资源的情况下(比如网商购物页面),为了节省用户流量和提高页面性能,可以在用户浏览到当前资源(当前窗口(可视区域)的大小)的时候,再对资源进行请求和加载。

懒加载实现原理

我们的图片要显示出来的话一般是借用img标签,然后把src属性写上图片的地址,才能把图片显示出来,那就想,我们先把图片不显示出来,就来写一个自定义属性字段,把这个属性字段的值写成图片地址,当图片在可视区域的范围的时候,就把自定义属性的值作为src的值。这就实现了懒加载。

<img src="" lazyload="true" data-original="https://t7.baidu.com/it/u=1732966997,2981886582&fm=193&f=GIF" alt=""
        class="image-item">
复制代码

data-original是我们自己定义的属性字段,它的值为我们要的图片地址。lazyload="true"是为了当图片加载出来后将图片不在需要懒加载了。(也可以不需要)

可视区域怎么找呢?

使用:document.documentElement.clientHeight可以获取到当前屏幕的高度。

当我们获取到高度之后,在想,如果这个图片在这个区域内,就让图片显示出来。

然后在想:当页面发生上滑的时候,可视区域的图片就会发生改变,所以当鼠标滚轮滚动的时候,在可视区域的图片就可能出去可视区域了,不在的可能这时候就进来了可视区域。所以我们要写一个监听事件。

  //获取可视区域的高度
    var viewHeight = document.documentElement.clientHeight
    //鼠标滚动的时候就要监听事件并且有一个函数去执行
    document.addEventListener('scroll', function () {
        //获取到页面上所有的img
        //判断某个是否进入可视区域
        //如果进入,就把它自身的data-original的值取出来放到src
        var arr = document.querySelectorAll('img[data-original][lazyload]')
        //这行代码的意思是获取所有的图片(具备data-original和lazyload的这两个属性的图片)
复制代码

当我们拿到所有的img时,利用循环去判断他们是否在可视区域内,在就加载出来,不在就暂时不加载。 所以需要满足的条件是图片的顶部在可视区域的高度里面,图片的底部也要在可视区域里面,也就是图片没有被划出去。

arr.forEach(item => {
            let rect = item.getBoundingClientRect()//用于一次性获取某个容器相对于浏览器上下左右的位置
            if (rect.top < viewHeight && rect.bottom >= 0) {
                item.src = item.dataset.original
                item.removeAttribute('data-original')
                item.removeAttribute('lazyload')
            }
        })
复制代码

完整代码:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<style>
    .image-item {
        height: 300px;
        display: block;
        margin-bottom: 50px;
    }
</style>

<body>
    <img src="" lazyload="true" data-original="https://t7.baidu.com/it/u=1732966997,2981886582&fm=193&f=GIF" alt=""
        class="image-item">
    <img src="" lazyload="true" data-original="https://t7.baidu.com/it/u=1785207335,3397162108&fm=193&f=GIF" alt=""
        class="image-item">
    <img src="" lazyload="true" data-original="https://t7.baidu.com/it/u=2581522032,2615939966&fm=193&f=GIF" alt=""
        class="image-item">
    <img src="" lazyload="true" data-original="https://t7.baidu.com/it/u=3423293041,3900166648&fm=193&f=GIF" alt=""
        class="image-item">
    <img src="" lazyload="true" data-original="https://t7.baidu.com/it/u=1417505637,1247476664&fm=193&f=GIF" alt=""
        class="image-item">
    <img src="" lazyload="true" data-original="https://t7.baidu.com/it/u=3659156856,3928250034&fm=193&f=GIF" alt=""
        class="image-item">
    <img src="" lazyload="true" data-original="https://t7.baidu.com/it/u=1416385889,2308474651&fm=193&f=GIF" alt=""
        class="image-item">
    <img src="" lazyload="true" data-original="https://t7.baidu.com/it/u=1599162854,1822154160&fm=193&f=GIF" alt=""
        class="image-item">
    <img src="" lazyload="true" data-original="https://t7.baidu.com/it/u=1476844859,894832600&fm=193&f=GIF" alt=""
        class="image-item">
    <img src="" lazyload="true" data-original="https://t7.baidu.com/it/u=3728410568,989468460&fm=193&f=GIF" alt=""
        class="image-item">
    <img src="" lazyload="true" data-original="https://t7.baidu.com/it/u=3696285528,2808863331&fm=193&f=GIF" alt=""
        class="image-item">

</body>
<script>
    //获取可视区域的高度
    var viewHeight = document.documentElement.clientHeight
    document.addEventListener('scroll', function () {
        //获取到页面上所有的img
        //判断某个是否进入可视区域
        //如果进入,就把它自身的data-original的值取出来放到src
        var arr = document.querySelectorAll('img[data-original][lazyload]')
        // console.log(arr);
        /* for(var i of arr){
        if(arr[i].offsettop()<i){
            
        }
    } */
        arr.forEach(item => {
            let rect = item.getBoundingClientRect()//用于一次性获取某个容器相对于浏览器上下左右的位置
            if (rect.top < viewHeight && rect.bottom >= 0) {
                item.src = item.dataset.original
                item.removeAttribute('data-original')
                item.removeAttribute('lazyload')
            }
        })
    })
</script>

</html>
复制代码

总结:懂得理论就很容易把代码写出来。

分类:
前端
标签: