• 如何实现图片懒加载功能?
  • 发布于 1个月前
  • 86 热度
    0 评论
懒加载的概念
懒加载(Lazy Loading)是一种延迟加载技术,指的是在需要使用某个对象或数据时才进行加载,而不是在系统启动或加载时就立即加载。懒加载可以在一定程度上提高系统的性能和资源利用率。例如:图片的加载,我们看不见的图片就不加载,能看到的图片就加载,加载完的图片就存入到浏览器的缓存当中,这样一个小小的功能就是懒加载!
我们进入到PC端的淘宝网官网:

我们可以发现,当我们在往下方滚动的时候,下方商品的图片在你看不到之前是没有加载的,而是当你滚到到它的时候,这个图片才加载,这就是懒加载的一个应用!


实现懒加载
懒加载思路
首先,我们说一下思路:
1.要实现懒加载,我们可以先让图片全部不显示。如何让图片加载:只要img的src属性里面有图片,就会加载,所以我们可以给img的src属性设置一个空 的图片,这样图片就不会加载了。
2.然后拿到用户的屏幕尺寸有多高,图片有多高,以及判断用户的屏幕能够放多少张图片!
3.先让能放的下图片有值,放不下的图片不放值(本质上就是判断图片是否在可视区域,然后把图片的值(图片地址)放到src上面)

接下来,我们就可以开始尝试手写懒加载了!
开始手写懒加载
首先,我们放十个img标签,并且自行搜索十张图片的地址! 并且设置一个类名img-item
<body>
    <img class='img-item' src="https://img.zcool.cn/community/011e0e5c231dcaa80121df9063b03f.jpg@1280w_1l_2o_100sh.jpg" alt="">
    <img class='img-item' src="https://img.zcool.cn/community/01427a5c63c7dba801213f26fa8f1f.jpg@1280w_1l_2o_100sh.jpg" alt="">
    <img class='img-item' src="https://img.zcool.cn/community/0132fb60a7171011013f472074ee82.jpg@1280w_1l_2o_100sh.jpg" alt="">
    <img class='img-item' src="https://pic2.zhimg.com/v2-ac79ec66a08cdbbfd36c3f9e4f307077_1440w.jpg" alt="">
    <img class='img-item' src="https://img.zcool.cn/community/01702360a7171511013e3b7d2249ef.jpg@1280w_1l_2o_100sh.jpg" alt="">
    <img class='img-item' src="https://img.zcool.cn/community/01c9e05da91bcea8012163bae9a7ea.jpg@2o.jpg" alt="">
    <img class='img-item' src="https://img.zcool.cn/community/010c155dcec2b0a8012053c0802a12.jpg@3000w_1l_0o_100sh.jpg" alt="">
    <img class='img-item' src="https://pic2.zhimg.com/v2-b2ab50d677e6f8a9101dae446dd99acd_r.jpg" alt="">
    <img class='img-item' src="https://img.3dmgame.com/uploads/images/thumbpicfirst/20180824/1535099402_352803.jpg" alt="">
    <img class='img-item' src="https://img.zcool.cn/community/0193a55b9df41ba8012099c8aedcd0.jpg@3000w_1l_0o_100sh.jpg" alt="">
</body>
由于图片尺寸问题,我们为了看得更加舒服,我们加点样式:
<style>
    .img-item{
        display: block;
        height: 300px;
        margin-top: 50px;
    }
</style>
将其变为块级元素,从上往下显示,设置图片高度为300px,上外边距为50px
接下来,怎么实现呢?
第一步:让图片全部不显示
根据我们的思路,我们先让图片全部不显示,并且我们知道html中,我可以使用自定义的属性存值作为过渡!所以我们修改一下body部分的图片
<body>
    <img class='img-item' src="" data-original="https://img.zcool.cn/community/011e0e5c231dcaa80121df9063b03f.jpg@1280w_1l_2o_100sh.jpg" alt="">
    <img class='img-item' src="" data-original="https://img.zcool.cn/community/01427a5c63c7dba801213f26fa8f1f.jpg@1280w_1l_2o_100sh.jpg" alt="">
    <img class='img-item' src="" data-original="https://img.zcool.cn/community/0132fb60a7171011013f472074ee82.jpg@1280w_1l_2o_100sh.jpg" alt="">
    <img class='img-item' src="" data-original="https://pic2.zhimg.com/v2-ac79ec66a08cdbbfd36c3f9e4f307077_1440w.jpg" alt="">
    <img class='img-item' src="" data-original="https://img.zcool.cn/community/01702360a7171511013e3b7d2249ef.jpg@1280w_1l_2o_100sh.jpg" alt="">
    <img class='img-item' src="" data-original="https://img.zcool.cn/community/01c9e05da91bcea8012163bae9a7ea.jpg@2o.jpg" alt="">
    <img class='img-item' src="" data-original="https://img.zcool.cn/community/010c155dcec2b0a8012053c0802a12.jpg@3000w_1l_0o_100sh.jpg" alt="">
    <img class='img-item' src="" data-original="https://pic2.zhimg.com/v2-b2ab50d677e6f8a9101dae446dd99acd_r.jpg" alt="">
    <img class='img-item' src="" data-original="https://img.3dmgame.com/uploads/images/thumbpicfirst/20180824/1535099402_352803.jpg" alt="">
    <img class='img-item' src="" data-original="https://img.zcool.cn/community/0193a55b9df41ba8012099c8aedcd0.jpg@3000w_1l_0o_100sh.jpg" alt="">
</body>
我们将src属性先置为空!然后我们自己定义一个data-original属性存我们图片的地址!
第二步:拿到用户可视界面的高度,图片相关的几何信息
接下来,我们开始第二步,拿到用户可视界面的高度,图片相关的几何信息,我们可以这样写一段js代码
<script>
    // 拿到可视区域的高度   innerHeight是window上独有的方法 别的用outerHeight或者innerHeight
    let viewHeight = window.innerHeight;
    // 拿到所有的img元素  img[data-original]只要具有data-original属性的img元素
    let imgs = document.querySelectorAll('img[data-original]');
    imgs.forEach(el=>{
        // getBoundingClientRect()专门获取容器的几何信息
        let rect = el.getBoundingClientRect()
        })

</script>
我们可以通过window.innerHeight;拿到用户可视区域的高度
注意!! innerHeight是window上独有的方法 别的用ofsetheight或者innerheight
再通过let imgs = document.querySelectorAll('img[data-original]');拿到所有具有data-original属性的img元素
getBoundingClientRect():专门获取容器的几何信息!
我们看看浏览器的输出,方便理解:
> bottom是指图片底部到可视界面顶部的距离
>
> top是指图片顶部到可视界面顶部的距离
我们这里没有用querySelectorAll而是querySelector则拿到的是第一个img元素!
第三步:判断图片是否在可视区域,然后把图片的值(图片地址)放到src上面
最后就是判断图片是否在可视区域,然后把图片的值(图片地址)放到src上面,我们再第二步的基础上可以封装一个方法!
<script>
    // 拿到可视觉区域的高度
    let viewHeight = window.innerHeight;
    function lazyLoad(){
        // 拿到所有的img元素  img[data-original]只要具有data-original属性的img元素
        let imgs = document.querySelectorAll('img[data-original]');
        imgs.forEach(el=>{
            // getBoundingClientRect()专门获取容器的几何信息
            let rect = el.getBoundingClientRect()
            if(rect.top<viewHeight){
                //进行赋值操作
                }
            }
        })
    }
</script>
我们可以想象一下,只要到图片顶部的距离小于可视区域的高度,我们就应该加载图片了!
所以这里用的是if(rect.top<viewHeight)
如果是正常情况下,data-original的值应该用一个中间变量来承接,而这个中间变量应该是一个image标签,一般情况下我们还需要使用createElement创建一个标签,但是image标签比较特殊,它天生具有构造函数!可以创建一个图片对象,所以我们接下来可以这样写:
if(rect.top<viewHeight){
    //进行赋值操作
    let image = new Image()
    image.src = el.dataset.original;
}
值得注意的是:data-original在js中有专有写法,写成dataset.original 。
接下来就是赋值了!
你可能会想直接这样写:
el.src = image.src
但是我们不会这样写,而是写成
if(rect.top<viewHeight){
    let image = new Image()
    image.src = el.dataset.original;
    image.onload = function(){
        el.src = image.src
    }
}
为什么这样写呢?这样写我们就通过onload函数的执行,当我们创造的image标签加载完毕的时候,我们才去把el.src赋值为image.src。
如果我们直接写el.src = image.src,图片加载的时候还是会空白一下,因为没有提前加载好,而加载是需要时间的,用onload封装的话,图片可以提前加载完毕,存入浏览器的缓存当中,能够更好的节约性能,节省时间!
当图片加载完毕了之后,我们再把data-original属性移除
if(rect.top<viewHeight){
    let image = new Image()
    image.src = el.dataset.original;
    image.onload = function(){
        el.src = image.src
    }
    // 图片加载完毕就移除属性
    el.removeAttribute('data-original')
}
写到这里,功能我们就实现了,我们调用一遍这个函数,同时添加一个事件监听器监听滚动事件,随着页面的滚动来加载图片,最终我们js部分就写成了这样!
<script>
    // 拿到可视觉区域的高度
    let viewHeight = window.innerHeight;
    function lazyLoad(){
        // 拿到所有的img元素
        let imgs = document.querySelectorAll('img[data-original]');
        imgs.forEach(el=>{
            // getBoundingClientRect()专门获取容器的几何信息
            let rect = el.getBoundingClientRect()
            if(rect.top<viewHeight){
                // img元素自带一个构造函数,可以创建一个图片对象
                let image = new Image()
                // js专有写法dataset.original; = data-original
                image.src = el.dataset.original;
                image.onload = function(){
                    el.src = image.src
                }
                // 图片加载完毕就移除属性
                el.removeAttribute('data-original')
            }
        })
    }
    lazyLoad()
    // 添加滚动事件监听器
    document.addEventListener('scroll',lazyLoad)
</script>
我们来看看现在页面的效果!

最后
今天,我们主要学习了前端图片资源加载优化手段的懒加载!介绍了实现懒加载的思路,以及如何实现懒加载!不知道,看到这里大家有没有学到这个知识点,如果有任何疑问欢迎大家在评论区留言哦!

著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
用户评论