js,图片懒加载,首屏加载速度,如何少量的代码兼容安卓ios的h5图片懒加载问题

图片懒加载是手机内嵌h5打开网页速度的优化方式之一,今天我就接受如何用最少的代码解决手机端的图片懒加载问题

因为公司使用的h5都是vue做的,但是其他框架使用方式是一样的

当后台数据相应后,一般我们会在html这么操作

<div class="image" v-for="item in artsToysProducts.list">
    <img :data-src="item.logoUrl" class="text" />
</div>

此时我们并没有真正的加载图片资源,而是用一个data-src来保存该图片标签将来也要加载的图片资源地址,最关键的是我们如何知道图片进入可视区域

/**
 * 懒加载图片,在图片进入可视区域才加载,对于图片很多的h5页面较为友好
 * demo在 activity/mainCenter
 */
var lazyLoad;
if( window.IntersectionObserver && /(iPhone)/.test(navigator.userAgent) ){//安卓手机对IntersectionObserve兼容不友好,所以我们针对安卓采用监听scroll
    lazyLoad = function ( element ) {
        const io = new IntersectionObserver(callback)// 实例化 默认基于当前视窗})  

        // 将图片的真实url设置为data-src src属性为占位图 元素可见时候替换src

        function callback(entries){  
            entries.forEach((item) => { // 遍历entries数组
                if(item.isIntersecting){ // 当前元素可见
                    item.target.src = item.target.dataset.src  // 替换src
                    io.unobserve(item.target)  // 停止观察当前元素 避免不可见时候再次调用callback函数
                }   
            })
            }
        setTimeout(()=>{
            let imgs = document.querySelectorAll( element )
            imgs.forEach((item)=>{  // io.observe接受一个DOM元素,添加多个监听 使用forEach
                io.observe(item)
            })
        },200)
    }
    
}else{
    lazyLoad = function ( element ){
        var getTop = function (e) {
            var T = e.offsetTop;
            while(e = e.offsetParent) {
                T += e.offsetTop;
            }
            return T;  
        }
     //判断是否进入可视区域
        var isInSight = function (el) {
            const bound = el.getBoundingClientRect();
            const clientHeight = window.innerHeight;
            //如果只考虑向下滚动加载
            //const clientWidth = window.innerWeight;
            return bound.top <= clientHeight + 0; 
        }
        var H = window.innerHeight;
        var S = document.documentElement.scrollTop || document.body.scrollTop;
        var lazyLoadImg = function (imgs) {
            var H = window.innerHeight;
            var S = document.documentElement.scrollTop || document.body.scrollTop;
            for (var i = 0; i < imgs.length; i++) {
                if( imgs[i]['isLoad'] ) {//如果该图片已经加载就跳过
                    continue;
                }
                //兼容处理,getBoundingClientRect的性能更好,但不保证较低的浏览器支持
                if( imgs[i].getBoundingClientRect  ){
                    if( isInSight( imgs[i] ) ){
                        imgs[i].src = imgs[i].getAttribute('data-src');
                        imgs[i]['isLoad'] = true;
                    }
                }
          //不支持getBoundingClientRect的我们判断滚动条距离加上可是区域是否大于当前图片距离文档顶部距离
          else if (H + S > getTop(imgs[i])) {
                    imgs[i].src = imgs[i].getAttribute('data-src');
                    imgs[i]['isLoad'] = true;
                }
            }
        }
    
        setTimeout( ( )=>{
            let imgs = document.querySelectorAll( element )
            window.onload = window.onscroll = function () {
                lazyLoadImg(imgs);
            }
            lazyLoadImg(imgs);
        },200)
    }
}

export default lazyLoad;

 

到此我们写好了监听图片进入可是区域的函数,接下来就是需要的页面调用该方法了

import lazyLoad from "../../utils/lazyLoad";

//vue页面数据相应后执行
this.$nextTick(function() {
        lazyLoad("[data-src]");
});

到此为止,在加载页面时候,只会在家在视图区域的图片资源,大大减少了http请求的数量,保证网页的打开速度,之后用户滚动才会不断在家进入视图的图片资源,主要是保证了首屏加载的速度