资讯专栏INFORMATION COLUMN

如何实现一个图片懒加载库

silenceboy / 2995人阅读

摘要:几个月前实现的一个图片懒加载库,地址。而这是我们可以优化的地方,这里我们使用函数去抖,调整后的代码如下至此,也算是实现了一个简单的图片懒加载库了,如有不足之处欢迎指正,大家一起交流交流

几个月前实现的一个图片懒加载库lazyload.js,github 地址。

需要实现的效果

相信大家都在网页中体验过图片懒加载,它应该有这样的效果:当图片进入我们的可视区时,加载这些图片。其原因相信大家都懂的——提高用户体验。

那么在代码中,我们就应该实现一下几点功能:
1.当页面加载完成时,先对可视区的图片进行加载;
2.给 scrollresize 事件添加监听;
3.当上述事件触发时,对在可视区的图片进行加载,并将加载过的图片移除。

具体实现

经过上面的分析,我们一步一步来实现图片懒加载。首先,我们先制定一些规则:
1.需要懒加载的图片标签应该带有值为 lazyload-img 的类;
2.需要懒加载的图片标签应该带有属性 data-src ,其值为图片的链接。

定义懒加载构造函数
function LazyLoad() {
    // 将所有需要懒加载的图片缓存在 imgList 数组中
    this.imgList = [].slice.call(document.querySelectorAll(".lazyload-img"));
    // 进行初始化操作
    this.init();
}

接下来想想我们的 init 方法应该做些什么?图片的加载是通过事件触发实现的,所以我在初始化的方法主要做的事情就是添加事件监听。

init 方法的实现放到最后来讲,接下来先来实现判断图片是否在可视区的方法 isInViewport

isInViewport方法的实现

在上代码前先来讲讲 getBoundingClientRect 这货,不知道大家对她了解多少。MDN上给出的定义是这样的:

Element.getBoundingClientRect()方法返回元素的大小及其相对于视口的位置。

什么意思呢,就是调用了这个方法后,返回了一个包含元素的宽高及其相对于浏览器视口左上角的位置信息。嗯.. 没看懂:( 简单点说呢,这个方法返回了一个对象,长这样:

{
    bottom: xx,
    left: xx,
    right: xx,
    top: xx,
    height: xx,
    width: xx
}

如果还是不太明白,可以直接到MDN看看。建议大家直接在控制台试试,说得再多不如动手试一试。
那了解这个方法后,有啥用?当然是用来判断图片是否在可视区咯,那我们来看看判断的逻辑:

LazyLoad.prototype.isInViewport = function (img) {
    var clientH = document.documentElement.clientHeight, // 浏览器视口高度
        clientW = document.documentElement.clientWidth, // 浏览器视口宽度
        imgPosOb = img.getBoundingClientRect(), // 获取img的位置信息
        imgT = imgPosOb.top,
        imgL = imgPosOb.left,
        imgH = imgPosOb.height,
        imgW = imgPosOb.width;

    // 判断逻辑
    // 不清楚的同学可以在草稿纸上画个图
    if( (imgT > -imgH && imgT < clientH) && (imgL > -imgW && imgL < clientW) ) {
        // inViewport
        return true;
    } else {
        return false;
    }
}

我们还有什么功能没实现?当然还有最重要的加载!

实现图片加载

这一步没啥好说的,直接上代码:

// 参数 imgList 是要加载的图片列表
LazyLoad.prototype.loadImg = function (inVpImgList) {
    var len = inVpImgList.length;
    var src = "";

    for (var i = 0; i < len; i++) {
        src = inVpImgList[i].getAttribute("data-src");
        inVpImgList[i].src = src;
        inVpImgList[i].removeAttribute("data-src");
        this.removeItem(inVpImgList[i]);
    }
};

// 不要忘了这一步
// 把加载过的图片移除
LazyLoad.prototype.removeItem = function (img) {
    var idx = this.imgList.indexOf(img);
    if(idx > -1) {
        this.imgList.splice(idx, 1);
    }
};
init方法的实现

最后,来完成我们的初始化方法:

LazyLoad.prototype.init = function () {
    var self = this;

    // callback函数即我们定义的事件触发后的回调函数
    function callback() {
        var imgInVp = [];
        var len = self.imgList.length;

        for (var i = 0; i < len; i++) {
            if(self.isInViewport(self.imgList[i])) {
                imgInVp.push(self.imgList[i]);
            }
        }

        self.loadImg(imgInVp);
    }

    callback();

    document.addEventListener("scroll", callback, false);
    window.addEventListener("resize", callback, false);
};

可能有哪位细心的小伙伴会发现我在 init 方法中调用了一次 callback。让我们再回头看看功能分析的第一点,你就明白了。那到这咱就完事了?不,还得优化一下。

优化

我们知道当我们在短时间内,连续地改变浏览器窗口大小或者滚动页面,会连续多次地触发 resizescroll 事件。而这是我们可以优化的地方,这里我们使用函数去抖,调整后的代码如下:

LazyLoad.prototype.init = function () {
    var self = this,
        timer = null;

    function callback() {
        timer && clearTimeout(timer);
        timer = setTimeout(function () {
            var imgInVp = [];
            var len = self.imgList.length;

            for (var i = 0; i < len; i++) {
                if(self.isInViewport(self.imgList[i])) {
                    imgInVp.push(self.imgList[i]);
                }
            }

            self.loadImg(imgInVp);
        }, 100);
    }

    callback();

    document.addEventListener("scroll", callback, false);
    window.addEventListener("resize", callback, false);
};

至此,也算是实现了一个简单的图片懒加载库了,如有不足之处欢迎指正,大家一起交流交流 :)

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/84879.html

相关文章

  • 淘宝新势力周H5性能优化实战

    摘要:前言淘宝新势力周春上新是命运石链路链路第一次承接级大促,面对级大促内容丰富且复杂的页面需求,链路遇到了一些性能问题,在未进行性能优化之前,搭建出来的页面,业务方普遍反馈页面卡顿严重,无法滑动。 前言 淘宝新势力周(春上新)是命运石kimi链路(H5链路)第一次承接S级大促,面对S级大促内容丰富且复杂的页面需求,kimi链路遇到了一些性能问题,在未进行性能优化之前,搭建出来的页面,业务方...

    Lionad-Morotar 评论0 收藏0
  • 性能更优越的小程序图片加载方式

    摘要:相交比例相交区域占参照区域的比例。阈值相交比例如果达到阈值,则会触发监听器的回调函数。 意义 懒加载或者可以说是延迟加载,针对非首屏或者用户看不到的地方延迟加载,有利于页面首屏加载速度快、节约了流量,用户体验好 实现方式 传统H5的懒加载方式都是通过监听页面的scroll事件来实现的,结合viewport的高度来判断。小程序也类似,通过监听页面onPageScroll事件获取当前滚动的...

    AJie 评论0 收藏0
  • 谈谈Web应用中的图片优化技巧及反思

    摘要:要注意老旧的浏览器不支持的特性,它会继续正常加载属性引用的图像。五安全地使用图片的优势这里不再赘述,简单来说 这篇文章,我们将一起探讨,web应用中能对图片进行什么样的优化,以及反思一些负优化手段 一、为什么要对图片进行优化 对于大多数前端工程师来说,图片就是UI设计师(或者自己)切好的图,你要做的只是把图片丢进项目中,然后用以链接的方式呈现在页面上,而且我们也经常把精力放在项目的打包...

    zone 评论0 收藏0
  • 手摸手-100行代码自己动手写个功能完整的图片加载插件

    摘要:景科同学的想法很简单,因为本人目前还是一个前端小白,只有通过不断的写,不断的学,在与的相爱相杀中才能更快速的进步。本项目是景科同学自写自测,虽然比较简单,但是不保证没有隐藏的。所以如果看官同学发现还望留言指正,景科同学在此以示感谢。 showImg(https://segmentfault.com/img/remote/1460000014251310?w=841&h=630); 本文...

    CompileYouth 评论0 收藏0
  • 看完你也想编写自己的 react 插件

    摘要:清楚自己想要什么样的组件,就自己动手撸呗。咱们先来看看它的效果吧如果大家有时间,窝还是鼓励大家自己动手实现一些小插件。于是自己就琢磨能否继承使用方法同时保持特有组件特性。需要确保已安装。 副标题----为什么我要写这个 react 插件 图片懒加载是项目中常用的功能,然而现有 react 懒加载组件库,用着都不是很爽了 ?。概括一下有如下几点: 没有只针对 image 懒加载组件。多...

    Vixb 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<