图片赖加载实现

图片加载概念引入

图片赖加载和图片预加载

图片预加载: 提前加载图片,当用户需要时,直接从缓存中渲染

图片赖加载: 懒加载主要是作为服务器前端优化。减少请求数或延迟请求数

懒加载实现原理

img的src属性用来表示图片的url。当src属性不为空时,就会向浏览器发送请求。那我们可以将真实地址存在一个自定义属性data-src中,当页面滚动时,将可视区域的图片的src值赋为真实的值。

实现的几种方式

  1. scrollTop(网页被卷去的高) + clientHeight(网页可视区域的高) > offsetTop(元素到offsetParent顶部的距离)
  2. el.getBoundingClientRect().top <= window.innerHeight
  3. IntersectionObserver(IE不支持)

代码实现

<!doctype html>
<html>

<head>
    <meta charset="utf-8">
    <title></title>
    <!--适应移动端-->
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <!--css样式-->
    <style>
        body {
            background-color: #EBEBEB
        }

        .aaa {
            background-color: #CB4F51;
            padding: 10px;
            display: block
        }

        img {
            background: #F1F1FA;
            width: 375px;
            height: 450px;
            display: block;
            margin: 10px auto;
            border: 0;
        }
    </style>

</head>

<body>


    <div>
        <img
            src="https://dss3.bdstatic.com/70cFv8Sh_Q1YnxGkpoWK1HF6hhy/it/u=2534506313,1688529724&amp;fm=26&amp;gp=0.jpg" />
        <img src="https://media-coa.feihe.com/coa/0/db0080e0-96cb-4eee-a5b3-ca0fdbf9bda6.png" />
        <img
            src="https://dss0.bdstatic.com/70cFvHSh_Q1YnxGkpoWK1HF6hhy/it/u=151472226,3497652000&fm=26&gp=0.jpg" />
        <img
            src="https://dss1.bdstatic.com/70cFuXSh_Q1YnxGkpoWK1HF6hhy/it/u=3892521478,1695688217&fm=26&gp=0.jpg" />
        <img
            src="https://dss0.bdstatic.com/70cFuHSh_Q1YnxGkpoWK1HF6hhy/it/u=1906469856,4113625838&fm=26&gp=0.jpg" />
        <img
            src="https://dss1.bdstatic.com/70cFvXSh_Q1YnxGkpoWK1HF6hhy/it/u=1776601493,3966748998&fm=26&gp=0.jpg" />
    </div>

    <script type="text/javascript">
        document.addEventListener("DOMContentLoaded", function () {
            var imgs = document.querySelectorAll('img');
            function throttle(func, wait) {  // 节流实现
                let timer
                return function (...args) {
                    if (!timer) {
                        timer = setTimeout(() => {
                            func(...args)
                            timer = null
                        }, wait);
                    }
                }
            }
            // 方法1: H + S > offsetTop
            // 1. offsetTop:元素到offsetParent顶部的距离
            // 2. offsetParent:距离元素最近的一个具有定位的祖宗元素(relative,absolute,fixed),若祖宗都不符合条件,offsetParent为body。
            // 网页被卷去的高: document.body.scrollTop;
            // 网页可见区域高: document.body.clientHeight;
            function lazyLoad1(imgs) {
                let S = document.documentElement.scrollTop || document.body.scrollTop
                let H = document.documentElement.clientHeight
                Array.from(imgs).forEach(img => {
                    if (S + H > img.offsetTop && !img.src) { //如果此时图片在可视区域,并且src没有数据
                        img.src = img.dataset.src // 将自定义属性赋值给src
                    }
                });
            }
            // 方法2:  el.getBoundingClientRect.top <= window.innerHeight
            // getBoundingClientRect: 该对象提供有关元素大小及其相对于视口的位置的信息。集合中有top, right, bottom, left等属性
            // window.innerHeight:返回窗口的文档显示区的高度
            function lazyLoad2(imgs) {
                function getBoolean(img) {
                    let bound = img.getBoundingClientRect()
                    let H = window.innerHeight
                    return bound.top < H
                } // 封装返回值
                Array.from(imgs).forEach((img) => {
                    if (getBoolean(img) && !img.src) {
                        img.src = img.dataset.src
                    }
                })
            }
            // 方法三
            // 方法3:IntersectionObserver(IE不支持)
            function lazyLoad3(imgs) {
                const io = new IntersectionObserver(
                    (changes) => {
                        console.log('changes', changes)
                        changes.forEach((change) => {
                            console.log('change', change)

                            var img = change.target;
                            // intersectionRatio 完全可见时为1
                            if (change.intersectionRatio > 0) {
                                if (!img.src) {
                                    img.src = img.dataset.src;
                                }
                            }
                            img.onload = img.onerror = () => io.unobserve(img);
                        })
                    }
                )
                imgs.forEach((img) => io.observe(img))
            }
            // lazyLoad3(imgs);
            // let throttleLazyLoad1 = throttle(lazyLoad1, 200) // 方法1节流实现
            let throttleLazyLoad2 = throttle(lazyLoad2, 200) // 方法2节流实现

            window.onload = window.onscroll = function () {
                // throttleLazyLoad1(imgs)
                throttleLazyLoad2(imgs)
            }
            //window.innerHeight属于BOM(浏览器对象模型),获取的高度包含横向滚动条

            // document.documentElement.clientHeight属于文档对象模型,不包含横向滚动条

            // document.body.clientHeight属于文档对象模型,body高度,如果设置body height=100%,document.documentElement.clientHeight=document.body.clientHeight
        })
    </script>

</body>

</html>

复制代码
© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享