图片懒加载的两种实现方式

Daming 2019-06-15
0条评论 501 次浏览
Daming 2019-06-150条评论 501 次浏览

图片懒加载的原理就是将图片真实地址定义在img标签自定义属性上,img标签src设置为一张默认图片,(例如loading图片)当图片标签位于视口范围内时 将自定义属性上的图片地址 设为img标签的src即可。

监听滚动事件的方式

遍历文档中所有图片, 通过getBoundingClientRect().top获取每个图片元素距离文档顶部的高度, 如果图片元素top的值小于 clientHeight表示元素在可视区域内,这时候将自定义属性上的图片地址赋值给图片元素的src属性即可。需要监听scroll事件,进行节流处理以较少性能开支。

代码如下:

    /**
     * 滚动执行
     */
    function handleScroll() {
        var imgArr = document.querySelectorAll("img[data-src]");
        var clientHeight = document.documentElement.clientHeight;
        [].forEach.call(imgArr, function (item, index) {
            if (item.getBoundingClientRect().top < clientHeight) {
                item.src = item.getAttribute("data-src");
            }
        })
    }


    /**
     * 节流
     * @param time
     * @param action
     * @returns {Function}
     */
    function throttle(time, action) {
        var timer = null;
        return function () {
            var context = this;
            var args = arguments;
            if (!timer) {
                timer = setTimeout(function () {
                    action.apply(context, args);
                    timer = null;
                }, time);
            }
        }
    }

    handleScroll();
    window.addEventListener("scroll", throttle(1000, handleScroll))

jquery版本:

 function handleScroll() {
         var imgArr = $("img[data-src]");
         var bodyScrollHeight = $(document).scrollTop();
         var wh = $(window).innerHeight();
         for (var i = 0; i < imgArr.length; i++) {
             var imgHeight = $(imgArr[i]).offset().top;//获取元素上边框相对于文档顶端的偏移量
             if (imgHeight < bodyScrollHeight + wh && imgHeight >= bodyScrollHeight) {
                 $(imgArr[i]).attr('src', imgArr.eq(i).attr("data-src"));
             }

         }
     }

通过IntersectionObserver API实现

通过监听scroll事件实现懒加载是非常消耗性能的,通过IntersectionObserver是监听目标元素与其祖先或视窗交叉状态的API,就是观察一个元素是否在视窗可见。

可以看到,交叉了就是说明当前元素在视窗里,当前就是可见的了。

IntersectionObserver就是一个构造函数,new 一个监视器:
var ob = new IntersectionObserver(callback, options)

ob实例的三个方法:

//对元素target添加监听,当target元素变化时,就会触发上述的回调
ob.observe(target);

// 移除一个监听,移除之后,target元素的可视区域变化,将不再触发前面的回调函数
ob.unobserve(target);

// 停止所有的监听
ob.disconnect();

我们获取文档中所有的图片并遍历他们传入每一个图片元素即可,当被观察的元素进入视窗 会触发callback

在callback中有entries参数,数组中的每一个元素,都是一个代表可视性变化的对象IntersectionObserverEntry,它包含元素的一些基本信息和变化的信息。

IntersectionObserverEntry 对象属性:

boundingClientRect 目标元素的矩形信息
intersectionRatio 相交区域和目标元素的比例值 intersectionRect/boundingClientRect 不可见时小于等于0
intersectionRect 目标元素和视窗(根)相交的矩形信息 可以称为相交区域
isIntersecting 目标元素当前是否可见 Boolean值 可见为true
rootBounds 根元素的矩形信息,没有指定根元素就是当前视窗的矩形信息
target 观察的目标元素
time 返回一个记录从IntersectionObserver的时间到交叉被触发的时间的时间戳

实现图片懒加载的代码如下:

 function lazyLoad() {
        var imgArr = document.querySelectorAll("img[data-src]");
        var ob = new IntersectionObserver(function (entries) {
            entries.forEach(function (entry) {
                //已经在视窗范围
                if (entry.isIntersecting) {
                    var img = entry.target;
                    img.src = img.getAttribute("data-src");
                }

            })
        });

        [].forEach.call(imgArr, function (item, index) {
            ob.observe(item);
        });
    }

    lazyLoad();

在线demo: https://demo.crazyming.com/?link=lazyLoad

1+

发表评论

电子邮件地址不会被公开。