最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • 图片延迟加载的2种实现方案

    正文概述 掘金(木卫三)   2021-02-24   426

    图片懒加载的意义

    虽然当代浏览器在渲染 DOM 树的时候。遇到 img 并不会阻碍 DOM 树的渲染(浏览器会开辟HTTP线程请求图片资源文件),但是在生成 RENDER TREE 后,浏览器进行渲染的时候,会把渲染树和图片一起进行绘制,这时就会遇到一些影响性能的(影页面第一次加载的速度)问题:

    1. 如果请求的图片资源过多,我们同时可以开辟的HTTP线程只有6个,这样图片资源预先的加载,会影晌其他资源的请求速度;
    2. 第一次绘制页面的时候,如果开始绘制图片,也需要消耗很多的时间,这样也影晌页面第一次打开的速度。

    所以对于这种情况:

    1. 我们一般都采用图片的懒加载(开始需要展示图片的位置,我们基于默认图或者一个空白的盒子占位,真实图片不加载,只有当页面的一次渲染完以及滚动到当前所在的区域时候,冉去加载真实的图片);
    2. 我们可以把图片 base64(虽然也会慢一,但是总比不做强多)。

    getBoundingClientRect

    getBoundingClientRect 用于获取某个元素相对于视窗的位置集合。集合中有top, right, bottom, left等属性。

    clientRect = lazyImageBox.getBoundingClientRect();
    
    1. clientRect.top:元素上边到视窗上边的距离;
    2. clientRect.right:元素右边到视窗左边的距离;
    3. clientRect.bottom:元素下边到视窗上边的距离;
    4. clientRect.left:元素左边到视窗左边的距离。

    图片延迟加载的2种实现方案

    盒子底边距离视口上面的距离 bottom 小于等于视口的高度,再开始加载图片。

    let lazyImageBox = document.querySelector('.lazyImageBox'),
        lazyImage = lazyImageBox.querySelector('img');
    
    const singleLazy = function singleLazy() {
        let trueImg = lazyImage.getAttribute('lazy-image');
        lazyImage.src = trueImg;
        lazyImage.onload = () => {
            // 真实图片加载成功
            lazyImage.style.opacity = 1;
        };
        lazyImageBox.isLoad = true;
    };
    
    const lazyFunc = function lazyFunc() {
        // 防止重复处理
        if (lazyImageBox.isLoad) return;
        let A = lazyImageBox.getBoundingClientRect().bottom,
            B = document.documentElement.clientHeight || document.body.clientHeight;
        if (A <= B) {
            singleLazy();
        }
    };
    
    // window.onscroll = lazyFunc; //默认浏览器会在最快的反应时间内,监听到scroll事件的触发,从而执行lazyFunc这个方法,这样导致触发频率太高了 -> 节流处理
    window.onscroll = throttle(lazyFunc);
    

    IntersectionObserver

    IntersectionObserver 可以自动"观察"元素是否可见。本质是目标元素与视口产生一个交叉区,所以这个 API 叫做"交叉观察器"。

    它的用法非常简单。

    let ob = new IntersectionObserver(callback, option);
    

    上面代码中,IntersectionObserver是浏览器原生提供的构造函数,接受两个参数:callback是可见性变化时的回调函数,option是配置对象(该参数可选)。

    构造函数的返回值是一个观察器实例。实例的observe方法可以指定观察哪个 DOM 节点。

    // 开始观察

    ob.observe(document.getElementById('example'));
    
    // 停止观察
    ob.unobserve(element);
    
    // 关闭观察器
    ob.disconnect();
    

    上面代码中,observe的参数是一个 DOM 节点对象。如果要观察多个节点,就要多次调用这个方法。

    callback 参数

    目标元素的可见性变化时,就会调用观察器的回调函数callback。

    callback一般会触发两次。一次是目标元素刚刚进入视口(开始可见),另一次是完全离开视口(开始不可见)

    let ob = new IntersectionObserver(changes => {
        // changes 是一个数组,包含所有监听的DOM元素和视口的交叉信息
        let item = changes[0],
            {
                isIntersecting,
                target
            } = item;
    });
    

    callback函数的参数(changes)是一个数组,每个成员都是一个IntersectionObserverEntry对象。举例来说,如果同时有两个被观察的对象的可见性发生变化,changes 数组就会有两个成员。

    IntersectionObserverEntry 对象

    IntersectionObserverEntry提供观察元素的信息,有八个属性。

    1. boundingClientRect:目标元素的矩形信息;
    2. intersectionRatio:相交区域和目标元素的比例值 ;
    3. intersectionRect:目标元素和视窗(根)相交的矩形信息 可以称为相交区域;
    4. isIntersecting:目标元素当前是否可见 Boolean值 可见为true;
    5. rootBounds:根元素的矩形信息,没有指定根元素就是当前视窗的矩形信息;
    6. target:观察的目标元素;
    7. time:返回一个记录从IntersectionObserver的时间到交叉被触发的时间的时间戳。
    

    intersectionRect/boundingClientRect:不可见时小于等于0;

    图片延迟加载的2种实现方案

    Option 对象

    IntersectionObserver构造函数的第二个参数是一个配置对象。它可以设置以下属性。

    threshold属性决定了什么时候触发回调函数。它是一个数组,每个成员都是一个门槛值,默认为[0],即交叉比例(intersectionRatio)达到0时触发回调函数。

    用户可以自定义这个数组。比如,[0, 0.25, 0.5, 0.75, 1]就表示当目标元素 0%、25%、50%、75%、100% 可见时,会触发回调函数。

    let lazyImageBox = document.querySelector('.lazyImageBox'),
        lazyImage = lazyImageBox.querySelector('img');
    const singleLazy = function singleLazy() {
        let trueImg = lazyImage.getAttribute('lazy-image');
        lazyImage.src = trueImg;
        lazyImage.onload = () => {
            lazyImage.style.opacity = 1;
        };
    };
    // 使用DOM监听器 IntersectionObserver:监听一个或者多个DOM元素和可视窗口的交叉信息
    let ob = new IntersectionObserver(changes => {
        // changes是一个数组,包含所有监听的DOM元素和视口的交叉信息
        let item = changes[0],
            {
                isIntersecting,
                target
            } = item;
        if (isIntersecting) {
            // 完全出现在视口中了
            singleLazy();
            ob.unobserve(lazyImageBox); //加载真实图片后,移除对盒子的监听
        }
    }, {
        threshold: [1]
    });
    ob.observe(lazyImageBox);
    

    总结

    图片延迟加载的2种实现方案

    IntersectionObserver 是新的浏览器 API , 可以更方便的实现图片延迟加载。但是 getBoundingClientRect 比起 IntersectionObserver 有更好的兼容性,因为IE无法兼容,所以要在IE实现这些功能,还是得老老实实使用基于 scroll 事件使用 getBoundingClientRect 来整。


    起源地下载网 » 图片延迟加载的2种实现方案

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元