什么?你还在使用这种懒加载方式?

导读


相信不少小伙伴在工做中都会遇到图片请求数量过多,致使出现页面会出现卡顿的状况,在咱们前端开发工做中,页面的渲染速度是十分重要的。
谈到这,咱们都知道其中最大的一个问题就是图片加载速度会拖累整个页面体验。不少页面,内容很丰富,页面很长,图片较多,好比说各类商城页面。这些页面图片数量多,并且比较大,少说百来K,多则上兆。有的时候没有必要一次性加载完。不然常会出现加载半张图片或是残缺,网速很差的有时候还会出现图片加载不出来等问题。
那么咱们可使用现有的技术,先显示可视区域中的图片,再使剩余图片未显示的图片和滚动条事件作交互,“滑到你,你再显示出来”,这也就是咱们常说的懒加载,来咱们看一下关于懒加载的定义。前端

懒加载(Load On Demand)是一种独特而又强大的数据获取方法,它可以在用户滚动页面的时候自动获取更多的数据,而新获得的数据不会影响原有数据的显示,同时最大程度上减小服务器端的资源耗用。git

关于懒加载的方式有不少种,在这里只会着重介绍其中两种,传统的懒加载方式以及交叉观察者这两种方式。github

传统的懒加载方式


传统的懒加载方式其实就是经过监听滚动轴的变化,去请求出如今可视区域的图片。数组

原理

将页面中的img标签src指向一张小图片或者src为空,而后定义data-src(这个属性能够自定义命名,我采用data-src)属性指向真实的图片。
浏览器

新建一个HTML文件

<div class="box">
    // 在这里咱们使用自定义属性data-src存储真实的图片地址
    <img style="margin-top: 600px;" class="img" src=""
        data-src="https://user-gold-cdn.xitu.io/2019/9/7/16d0a7d1e26e2947?w=533&h=300&f=jpeg&s=44672"
        alt="">
    <img class="img" src=""
        data-src="https://user-gold-cdn.xitu.io/2019/9/7/16d0a7d1e28ba479?w=500&h=463&f=jpeg&s=10435"
        alt="">
    <img class="img" src=""
        data-src="https://user-gold-cdn.xitu.io/2019/9/7/16d0a7d1e5b3c69c?w=579&h=300&f=jpeg&s=23132"
        alt="">
    <img class="img" src=""
        data-src="https://user-gold-cdn.xitu.io/2019/9/7/16d0a7d1e60d6bc9?w=500&h=394&f=jpeg&s=27013"
        alt="">
    <img class="img" src=""
        data-src="https://user-gold-cdn.xitu.io/2019/9/7/16d0a7d1e5ac147c?w=500&h=313&f=jpeg&s=29734"
        alt="">
    <img class="img" src=""
        data-src="https://user-gold-cdn.xitu.io/2019/9/7/16d0a7d1e5d0a8ef?w=428&h=600&f=jpeg&s=37727"
        alt="">
    <img class="img" src=""
        data-src="https://user-gold-cdn.xitu.io/2019/9/7/16d0a7d2033996bc?w=500&h=325&f=jpeg&s=9951"
        alt="">
</div>

复制代码

新建一个CSS文件

.box {
    width: 800px;
    height: 400px;
    border: 1px solid;
    overflow: auto;
}

.img {
    width: 100px;
    height: 100px;
    border: 1px solid;
    display: block;
    margin: 40px auto;
}

复制代码

在这里咱们基本能够实现一个这样的界面bash

实现懒加载

1.首先咱们先去获取父级元素以及子元素

const box = document.querySelector('.box');
const imgs = document.querySelectorAll('.img');

2.监听父级滚动轴变化

box.addEventListener('scroll', handleListenScroll);

3.实现监听函数

function handleListenScroll() {
    //获取父级滚动轴距离顶部距离
    var scrollTop = box.scrollTop;
    
    //获取父级高度
    var divHeight = box.clientHeight;

    for (var i = 0; i < imgs.length; i++){
        if (imgs[i].offsetTop < divHeight + scrollTop) {
          imgs[i].src = imgs[i].getAttribute('data-src');
        }
    }
}

这样一个简单的懒加载就实现了,咱们看下效果。

复制代码

优化

若是直接将函数绑定在scroll事件上,当页面滚动时,函数会被高频触发,这很是影响浏览器的性能。服务器

所谓节流,就是当持续触发事件时,保证必定时间段内只调用一次事件处理函数。这里也许会有小伙伴说了,防抖呢?先说一下防抖的概念吧,当持续触发事件时,必定时间段内没有再触发事件,事件处理函数才会执行一次,若是设定的时间到来以前,又一次触发了事件,就从新开始延时。根据咱们的场景,显然在这里使用防抖是不太合适的。app

box.addEventListener('scroll', throttle(handleListenScroll, 500));

//节流实现
function throttle(func, delay) {
    var previous = 0;
    return function () {
        let now = Date.now();
        let context = this;
        let args = arguments;
        if (now - previous > delay) {
            func.apply(context, args);
            previous = now;
        }
    };
}

复制代码

小tip 在使用的时候咱们也能够给每一个图片一个默认图片,等图片出如今可视区域的时候进行一个替换。异步


交叉观察者


交叉观察者其实就是利用IntersectionObserver接口 (从属于Intersection Observer API) 提供了一种异步观察目标元素与其祖先元素或顶级文档视窗(viewport)交叉状态的方法。祖先元素与视窗(viewport)被称为根(root)。函数

用通俗的话来说就是判断目标元素有没有和父级元素产生交叉行为,一张图说明一切,画的丑,请见谅~~

兼容性

呃呃呃, IE几乎全军覆没,不过,有官方提供过的polyfill,啥都不用怕,点这里

属性和方法

属性 介绍
root 所监听对象的具体祖先元素(element)。若是未传入值或值为null,则默认使用顶级文档的视窗。
rootMargin 计算交叉时添加到根(root)边界盒bounding box的矩形偏移量, 能够有效的缩小或扩大根的断定范围从而知足计算须要
thresholds 一个包含阈值的列表, 按升序排列, 列表中的每一个阈值都是监听对象的交叉区域与边界区域的比率。

方法 介绍
disconnect() 使IntersectionObserver对象中止监听工做
observe() 使IntersectionObserver开始监听一个目标元素。
takeRecords() 返回全部观察目标的IntersectionObserverEntry对象数组。
unobserve() 使IntersectionObserver中止监听特定目标元素。

使用

1.新建一个IntersectionObserver对象。

const observer = new IntersectionObserver(entries => {
    // 发生交叉目标元素集合
    console.log(entries);
}, option);
    
在这里callback会返回给咱们当前已监听而且发生了交叉的目标集合,咱们看一下具体信息。
    
复制代码

属性 介绍
boundingClientRect 空间信息
target 目标元素
isIntersecting 是否发生交叉

2.监听目标元素

const box = document.querySelector('.box');
const imgs = document.querySelectorAll('.img');

const observer = new IntersectionObserver(entries => {
    // 发生交叉目标元素集合
    entries.forEach(item => {
        // 判断是否发生交叉
        if (item.isIntersecting) {
            // 替换目标元素Url
            item.target.src = item.target.dataset.src;
            // 取消监听此目标元素
            observer.unobserve(item.target);
        }
    });
}, {
    root: box, // 父级元素
    rootMargin: '20px 0px 100px 0px' // 设置偏移 咱们能够设置在目标元素距离底部100px的时候发送请求
});

imgs.forEach(item => {
    // 监听目标元素
    observer.observe(item);
});

复制代码

实现

以上就是使用IntersectionObserver实现懒加载的过程,是否是很简单呢,在这里咱们再也不须要去监听滚动条的变化,只须要根据返回给咱们的元素集合就能够实现。还要记住必须是子元素跟父元素发生交叉,是不能够去检查两个非父子关系的交叉的状况哦~~


综上 就是我对于懒加载一点小看法,也但愿将来咱们的页面更加流畅,so,先从懒加载开始吧~~。其实懒加载只是经过IntersectionObserver实现的一点小功能,IntersectionObserver还能够帮咱们实现吸顶触底这些功能,感兴趣的小伙伴能够去试试哦。最后,文中若有错误,欢迎在评论区指正,若是这篇文章帮助到了你,欢迎点赞👍和关注,😀。

推荐阅读


参考


相关文章
相关标签/搜索