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

    正文概述 掘金(超能小可爱yy)   2021-06-24   376

    一、图片懒加载意义

    虽然当代浏览器在渲染DOM树的时候,遇到img并不会阻碍DOM树的渲染(浏览器会开辟HTTP线程请求图片资源文件),但是在生成RENDER TREE后,浏览器进行渲染的时候,会把渲染树和图片一起进行绘制

    会遇到一些影响性能(影响页面第一次加载的速度)问题:

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

    解决方案:

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

    二、实现方案

    1. 旧:基于盒子模型( 或者getBoundingClientRect() ),我们判断出是否加载图片,在滚动条滚动中随时进行判断处理(需要做节流);
    2. 新:IntersectionObserver基于元素的监听,一体化解决懒加载问题
    /*
    IntersectionObserver监听,当DOM元素出现和离开视口的时候触发回调函数
        observer = new IntersectionObserver([callback], [options])
        threshold 默认值是[0],我们可以基于数组的方式管控,元素相对于视口的交叉位置,在什么程度下触发
        回调函数
    */
    observer.observe([DOM元素])    监听
    observer.unobserve([DOM元素])  移除监听
    
    //例:
    let observer = new IntersectionObserver( changes => {
        //changes包含所有监听的DOM信息
        changes.forEach( item => {
            let { isIntersecting, target } = item;
            if(isIntersecting) {
                lazyImg(target);
                observer.unobserve(target);
            }
        });
    }, {
        //控制什么时候触发回调
        threshold: [1]
    } )
    

    三、无限下拉加载

    /*
    在整个卡片下面加一个盒子,如起名为bottomBox,设置高度为100px,监听盒子即可,如果监听到这个盒子已经
    露头,说明已经到达底部,就可以再加载一次真实数据
    */
    let observer2 = new IntersectionObserver(changes => {
        let isLoadMore = false; //是否正在加载更多数据
        let isIntersecting = changes[0].isIntersecting;
        if(isIntersecting) {
            //到达底部了
            if(isLoadMore) return;
            isLoadMore = true;
            //重新发送请求即可 
        }
    }, {
        threshold: [0]
    })
    

    四、图片懒加载插件封装

    /*
    图片懒加载插件:只处理图片的延迟加载
        规定:
            1. 结构:图片放在一个盒子中,盒子是图片没有加载之前的占位;需要延迟加载的图片,src是空的,
            data-image存放真实的地址,我们默认认为所有拥有data-image属性的图片都要做延迟加载
            
            <div>
                <img src="" data-img="image/1.png" />
            </div>
            
            2.导入JS后,我们可以暴露出一个API(例如init),只要执行init方法就会开始进行图片延迟加载,而且还可以支持一些配置参数:
            {
                threshold: [1],    //什么时候延迟加载
                animate: true,     //是否有动画:渐隐渐现(需要给图片设置opacity/transtion样式)
                attr: 'data-img',  //具备哪些属性的进行延迟加载(要求属性值一定是真实存在地址)
                onload: function(img){}  //每一张图片加载完要触发的函数
            }
    */
    (function () {
        constructor(options) {
            //把配置项挂载到实例上
            this.options = options;
            
            //创建一个监听的实例
            let config = {
                threshold: options.threshold
            };
            this.observe = new IntersectionObserver(this.callback.bind(this), config)}
        
        //原型方法
        watch() {
            let { attr, animate } = this.options;
            //监听元素
            let allImgs = Array.from(document.querySelectorAll(`img[${attr}]`));
            allImgs.forEach(item => {
                //如果需要实现渐隐渐现动画,需要设置样式
                if(animate) {
                    item.style.opacity = 0;
                    item.style.transtion = "opacity .3s ease";
                }
                //监听图片所在的div
                this.observe.observe(item.parentNode);
            });
        }
        
        callback(changes){
            //回调触发
            changes.forEach( item => {
                let { isIntersecting, target } = item;
                if(isIntersecting) {
                    this.lazyImg(target);
                    observer.unobserve(target);
                }
            });
        }
        
        lazyImg(target){
            //单张图片延迟加载
            let { attr, animate, onload } = this.options;
            let img = target.querySelector('img'),
                trueImg = img.getAttribute(`${attr}`);
            img.src = trueImg;
            img.onload = () => {
                //图片加载成功
                img.style.display = 'block';
                if(animate) {
                    img.offsetWidth; //目的:刷新浏览器渲染队列
                    img.style.opacity = 1; 
                };
                //单张图片加载完都触发这个函数
                onload.call(this, img)
                img.removeAttribute(`${attr}`);
            }
            
        }
        
        class LazyImg {
            //静态对象
            static init( options={} ){
                //参数初始化
                options = Object.assign({
                    threshold: [1],
                    animate: true,
                    attr: 'data-image',
                    onload: function(){}
                }, options)
                //创造类的实例
                return new LazyImg(options);
            }
        }
        if(typeof window !== 'undefined') {
            window.LazyImg = LazyImg;
        }
        if(typeof module !=='undefined' && typeof module.exports !== 'undefined'){
            module.exports = LazyImg;
        }
    })();
    LazyImg.init();
    

    起源地下载网 » 图片延迟加载和无限数据加载

    常见问题FAQ

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

    发表评论

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

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

    联系作者

    请选择支付方式

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