前端性能优化第一弹:图片懒加载

前言

📢最近准备春招啦了,所以整理了一些前端高频大厂面试题,分享给大家,如有问题欢迎留言指正,面试专栏我会长期更新,欢迎大家点赞🤞、收藏📌,关注➕,感谢!

在最近的面试中经常被问到这些问题,我写这篇文章总结一下,自己也可以复习巩固一下,也为大家分享一下。那就开始吧

原生js实现

首先我们来说一说实现思路吧,当一个img图片中的src中有图片地址时,就是发送http请求,我们可以先不设置图片地址。接下来获取电脑可视窗口的宽度,获取图片的顶部到可视窗口到顶部的距离,当图片的顶部到可视窗口到顶部的距离小于等于电脑可视窗口的宽度时,把图片地址赋值给img。展示代码

<style>
        img {
            height: 300px;
            margin-bottom: 50px;
        }
    </style>
</head>

<body>
    <div id="box">
        <img src=""
            data-original="https://img0.baidu.com/it/u=2093146887,2209093944&fm=253&fmt=auto&app=138&f=JPEG?w=800&h=500"
            alt="">
        <img src=""
            data-original="https://img1.baidu.com/it/u=626755183,2526908742&fm=253&fmt=auto&app=138&f=JPEG?w=800&h=500"
            alt="">
        <img src=""
            data-original="https://img2.baidu.com/it/u=2338675418,2306268000&fm=253&fmt=auto&app=138&f=JPEG?w=889&h=500"
            alt="">
        <img src=""
            data-original="https://img0.baidu.com/it/u=48465464,3484394863&fm=253&fmt=auto&app=138&f=JPEG?w=889&h=500"
            alt="">
        <img src="" data-original="https://img0.baidu.com/it/u=2788901948,3907873318&fm=253&fmt=auto?w=500&h=281"
            alt="">
        <img src=""
            data-original="https://img1.baidu.com/it/u=3007039639,472852969&fm=253&fmt=auto&app=120&f=JPEG?w=1280&h=800"
            alt="">
        <img src=""
            data-original="https://img1.baidu.com/it/u=1407687539,521000387&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=291"
            alt="">
        <img src=""
            data-original="https://img0.baidu.com/it/u=3993238299,896819757&fm=253&fmt=auto&app=138&f=JPEG?w=889&h=500"
            alt="">
        <img src="" data-original="https://img2.baidu.com/it/u=4120653798,1128660508&fm=253&fmt=auto?w=889&h=500"
            alt="">
        <img src=""
            data-original="https://img1.baidu.com/it/u=2632231576,1274688417&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=281"
            alt="">
    </div>
    <script>
        //获取屏幕的可视高度
        const viewportHeight = window.innerHeight;

        function lazyLoad() {
            // 选择你的图片,替换 'img[data-original]' 为你的图片类名或选择器
            const images = document.querySelectorAll('img[data-original]');
            images.forEach(item => {
                //// 计算图片顶部到可视区域顶部的距离
                const rect = item.getBoundingClientRect();
                if (rect.top < viewportHeight) {
                    item.src = item.dataset.original
                    item.removeAttribute('data-original')
                }
            })

        }

        lazyLoad()
        document.addEventListener('scroll', lazyLoad)

在这里我们用到了这是一个自定义的属性,通常用于存储图片的原始源文件的 URL。innerHeight获取屏幕的可视高度,getBoundingClientRect()计算图片顶部到可视区域顶部的距离,dataset``.dataset: 这是一个 DOM 元素属性,它提供了一种访问元素上所有自定义数据属性的方式。自定义数据属性是以 data- 开头的属性,比如 data-original,在通过监听scroll事件来监听

IntersectionObserver 方法

IntersectionObserver 接口(从属于 Intersection Observer API)提供了一种异步观察目标元素与其祖先元素或顶级文档视口(viewport)交叉状态的方法。其祖先元素或视口被称为根(root)。
这个原理个上面的原理差不多代码如下

 <style>
        #box {
            width: 100vw;
            height: 100vh;
            overflow: scroll;
        }

        img {
            height: 300px;
            margin-bottom: 50px;
            display: block;
        }
    </style>


    <script>
        // 获取所有需要延迟加载的图片
        const lazyImages = document.querySelectorAll('img[data-original]');
        const box = document.getElementById('box')
        // 创建 IntersectionObserver 实例
        const observer = new IntersectionObserver((entries, observer) => {
            // 对于每个进入视窗的元素
            entries.forEach(entry => {
                // 如果元素进入视窗
                if (entry.isIntersecting) {
                    entry.target.src = entry.target.dataset.original || ''
                    entry.target.removeAttribute('data-original')


                    // 加载完后移除监听
                    observer.unobserve(entry.target);
                }
            });
        }, {
          
            // 设置阈值为 0
            threshold: 0,
           
        });

        // 为每个需要延迟加载的图片添加观察者
        lazyImages.forEach(image => {
            observer.observe(image);
        });
    </script>
</body>

这个用到了IntersectionObserver 的原理,我对它还没有深入的理解,这个是大佬IntersectionObserver你们可以去看看理解一下

如觉得本文对你有帮助的话,欢迎点赞❤❤❤,写作不易,持续输出的背后是无数个日夜的积累,您的点赞是持续写作的动力,感谢支持!有什么写错的,需要增加的可以在评论区留言 谢谢大家支持

原文链接:https://juejin.cn/post/7358688805157666853 作者:扯蛋蛋

(0)
上一篇 2024年4月18日 上午10:31
下一篇 2024年4月18日 上午10:41

相关推荐

发表回复

登录后才能评论