如何实现图片懒加载

<!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>图片懒加载</title>
</head>

<style>
    * {
        margin: 0;
        padding: 0;
    }

    .lazyload-img {
        display: block;
        width: 600px;
        height: 400px;
        margin: 50px;
    }
</style>

<body>
    <div class="wrap">
        <!-- 使用一张默认图片占位,在标签上设置一个自定义的data-url属性,该属性的值存放着图片的真实请求地址,图片进入可视区域之后,获取img标签上的data-url属性的值,把它设置到src属性上 -->
        <img src="https://www.yswx.cn/upload/202204/12/202204121846289521.jpg" class="lazyload-img"
            data-url="https://oss.lingjiang.com/images/live/2023/02/21/7994c524a88742858660825de9d3c01d.png">
        <img src="https://www.yswx.cn/upload/202204/12/202204121846289521.jpg" class="lazyload-img"
            data-url="https://oss.lingjiang.com/images/goods/2022/12/05/c82d2a5322034564b25544b9bcf3bbd8.png">
        <img src="https://www.yswx.cn/upload/202204/12/202204121846289521.jpg" class="lazyload-img"
            data-url="https://oss.lingjiang.com/images/goods/2022/11/21/60ec30da96de4ca7bcb235e8aece12c0.jpg">
        <img src="https://www.yswx.cn/upload/202204/12/202204121846289521.jpg" class="lazyload-img"
            data-url="https://oss.lingjiang.com/images/goods/2022/11/16/a2b85d311e764247a3f8f104f84ea2f0.jpg">
        <img src="https://www.yswx.cn/upload/202204/12/202204121846289521.jpg" class="lazyload-img"
            data-url="https://oss.lingjiang.com/images/goods/2022/11/16/880ea15b19db4d4eb5670df1195721d8.jpg">
        <img src="https://www.yswx.cn/upload/202204/12/202204121846289521.jpg" class="lazyload-img"
            data-url="https://oss.lingjiang.com/images/goods/2022/11/16/2f4468ae63e74696a9b9b4e1e3f2ee7f.jpg">
        <img src="https://www.yswx.cn/upload/202204/12/202204121846289521.jpg" class="lazyload-img"
            data-url="https://oss.lingjiang.com/images/goods/2022/11/16/bb8e5cfab51e4be3845c500ee3aad653.jpg">
        <img src="https://www.yswx.cn/upload/202204/12/202204121846289521.jpg" class="lazyload-img"
            data-url="https://oss.lingjiang.com/images/live/2022/09/02/a66ff27fba3e49f1ac0f0ecbfd3eaed9.png">
        <img src="https://www.yswx.cn/upload/202204/12/202204121846289521.jpg" class="lazyload-img"
            data-url="https://oss.lingjiang.com/images/live/2022/08/23/378dabc2872e41ca90666502fce78bb7.png">
    </div>
</body>

</html>

<script>
    /**
     * @title 图片懒加载
     * @principle  原理:当图片进入到可视区时,再真正加载图片
     * @meaning 好处:减少无效资源加载,减少页面http请求,提高页面加载速度,优化用户体验
     * @returns
     */

    // 获取当前文档流的根节点,用于获取当前窗口的高度(clientHeight)和宽度(clientWidth),便于判断图片是否在可视区内
    let rootElement = document.documentElement;

    // 获取所有img标签,并转化为数组
    let arrImgList = Array.from(document.querySelectorAll('.lazyload-img'));

    // 封装一个方法判断某一个元素是否在可视区域
    function fnIsVisible(element) {
        // getBoundingClientRect: 所有的元素节点上都有这个方法,提供当前元素节点的大小、位置等信息,就是 CSS 盒状模型的所有信息。
        let rect = element.getBoundingClientRect();
        console.log(rect)
        // 节点距离顶部的位置小于窗口高度、距离窗口底部的位置大于0、距离左侧的位置小于窗口宽度、距离窗口右侧的位置大于0,那么就可以证明该节点在可视区范围内
        return rect.top < rootElement.clientHeight && rect.bottom > 0 && rect.left < rootElement.clientWidth && rect.right > 0;
    }

    // 封装一个方法,动态设置img标签的scr属性
    function fnLoadImg() {
        for (let i = 0; i < arrImgList.length; i++) {
            let img = arrImgList[i];
            // 如果在可视区,设置scr属性
            if (fnIsVisible(img)) {
                img.src = img.getAttribute('data-url');
                // 图片加载后,下次就不用在设置了,直接将此节点移除
                arrImgList.splice(i, 1);
                i--;
            }
        }
    }
    // 一开始先执行一次,把在第一次进入页面时在可视区域的图片加载出来
    fnLoadImg();

    // 监听滚动事件,频繁判断图片是否进入到可视区
    let timer = null; // 性能优化,防抖
    document.addEventListener('scroll', () => {
        // 防抖处理
        if (timer) clearTimeout(timer);
        timer = setTimeout(() => {
            // 页面滚动的时候,不断有新的图片进入可视区域,此时再调用lazyloadImg函数
            fnLoadImg();
        }, 100);
    })

    /**
     * 面试回答
     * 1.首先获取根节点 通过clientHeight和clientWidth获取窗口宽度和高度
     * 2.在获取所有图片标签集合,并转换为数组
     * 3.封装一个方法,该方法用于循环数组并通过 getBoundingClientRect 方法获取到节点位置,与窗口宽度高度做对比,进而判断出图片是否在可视区范围内,如果在可视区内,就设置img的src属性
     * 3.监听滚动事件,触发滚动事件,就重复调用上述方法,从而实现图片懒加载。(监听滚动事件,采用防抖,优化性能)
    */

</script>

 

posted @ 2023-03-08 15:30  我是一名好程序员  阅读(184)  评论(0编辑  收藏  举报