热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

一起来实现图片滚动懒加载

图片一直是网络资源占用大户,对于一个前端有几百张图片的网站来说,如果首屏即加载所有图片(无论这些图片有没有被用户看到)&#x

图片一直是网络资源占用大户,对于一个前端有几百张图片的网站来说,如果首屏即加载所有图片(无论这些图片有没有被用户看到),那无疑是既浪费网络资源,又伤害用户体验的事。因此,图片懒加载,是提高前端性能的刚需所在。

目前,淘宝网、知乎等大流量网站都已经使用了图片滚动懒加载的方案——仅当图片滚入视窗,被用户看到的时候,才会去真正加载。

基本原理

图片滚动懒加载的原理非常简单:基于标签,在初次加载时,不把图片url放在src属性中,而是自定义一个属性,例如data-src。然后检测"scroll","resize"等窗体事件,判断图片是否进入了可视范围。如果进入,则将data-src的字段替换到src,此时浏览器会自动去加载对应图片资源。

Talking is cheap, show you the code

首先是不添加src的img标签,新增data-src用于放置图片url:

<img class&#61;"lazyImg" data-src&#61;"http://xxx.xxx.com"/>

然后&#xff0c;我们需要新增一个数组队列&#xff0c;来储存所有未加载的img节点&#xff1a;

var lazyImg&#61;[].slice.call(document.querySelectorAll(".lazyImg"));

为了方便&#xff0c;这里直接用querySelectorAll来获取所有img节点。注意因为NodeList是只读数组&#xff0c;因此需要将其转化为数组&#xff0c;方便之后的增删。在真实环境中&#xff0c;还需给每个成员添加其最近的可滚动祖先节点的引用&#xff0c;即el.parentNode。

最关键的部分来了&#xff0c;如何判断图片是否进入了可视区域&#xff0c;以及实现加载呢&#xff1f;

// 参数传入lazyImg数组
function loadImage(images){let scrollParent,src,el;for(let i &#61; 0;i //img所属的最近的可滚动祖先节点el&#61;images[i].el;//offset为预留的预加载距离if(checkInView(el,scrollParent,this.options.offset)){src&#61;el.dataset.src;el.setAttribute("src",src);images.splice(i--,1); //将该img元素移除}}
}

上面提到的scrollParent是带有scroll特性的祖先节点&#xff0c;具体实现&#xff1a;可使用getComputedStyle检查父节点是否设置了overflow(overflow-x,overflow-y)为"auto"或"scroll"&#xff0c;不断循环直到找到满足条件的祖先节点。

下面封装了判断是否在可视区域的函数&#xff1a;

const checkInView&#61;(el,scrollParent,offset)&#61;>{let scrollTop,scrollLeft,clientH,clientW;if(scrollParent &#61;&#61;&#61; window) {scrollTop&#61;document.documentElement.scrollTop||document.body.scrollTop;scrollLeft&#61;document.documentElement.scrollLeft||document.body.scrollLeft;clientH&#61;document.documentElement.clientHeight||document.body.clientHeight;clientW&#61;document.documentElement.clientWidth||document.body.clientWidth;}else {scrollTop &#61; scrollParent.scrollTop;scrollLeft&#61;scrollParent.scrollLeft;clientH &#61; scrollParent.clientHeight;clientW&#61;scrollParent.clientWidth;}while(el!&#61;scrollParent && el!&#61;null){let borderWidth&#61;parseInt(getStyle(el,"border-width"));offsetTop&#43;&#61;el.offsetTop&#43;borderWidth;offsetLeft&#43;&#61;el.offsetLeft&#43;borderWidth;el&#61;el.offsetParent;}//在这里判断是否滚入可视区域。offset为预留的预加载距离if(scrollTop&#43;clientH>el.offsetTop-offset && scrollLeft&#43;clientW>el.offsetLeft-offset){return true;}else return false;
}

最后再让各自的scrollParent监听"scroll"&#xff0c;"resize"等事件即可&#xff1a;

function initListener(el){let scrollParent&#61;getScrollParent(el);if(this.scrollParent.indexOf(scrollParent)<0){position &#61; getStyle(scrollParent, "position"); //若为window则返回nullif (position&#61;&#61;&#61;"" || position &#61;&#61;&#61; "static") scrollParent.style.position &#61; "relative"; //确保能检测到正确的offsetTop和offsetLeftthis.scrollParent.push(scrollParent); //数组用于保存已经监听的可滚动祖先节点this.eventsList.forEach((event)&#61;>{scrollParent.addEventListener(event,this.loadImage.bind(this));})}
}

以上便是实现图片懒加载的关键代码。

如果有动态添加的img标签&#xff0c;该怎么办呢&#xff1f;其实很简单&#xff0c;只需要将新增的img元素push进这个lazyImg数组队列中&#xff0c;然后调用InitListener即可。

完整实现

利用以上原理&#xff0c;我实现了一个基于vue2.x的图片懒加载的插件&#xff0c;完整代码可参考这里vue-lazyload-images。

转:https://juejin.im/post/58e454ddb123db15eb79369a



推荐阅读
  • 在尝试对 QQmlPropertyMap 类进行测试驱动开发时,发现其派生类中无法正常调用槽函数或 Q_INVOKABLE 方法。这可能是由于 QQmlPropertyMap 的内部实现机制导致的,需要进一步研究以找到解决方案。 ... [详细]
  • 本文详细介绍了 PHP 中对象的生命周期、内存管理和魔术方法的使用,包括对象的自动销毁、析构函数的作用以及各种魔术方法的具体应用场景。 ... [详细]
  • 本指南介绍了如何在ASP.NET Web应用程序中利用C#和JavaScript实现基于指纹识别的登录系统。通过集成指纹识别技术,用户无需输入传统的登录ID即可完成身份验证,从而提升用户体验和安全性。我们将详细探讨如何配置和部署这一功能,确保系统的稳定性和可靠性。 ... [详细]
  • C++ 异步编程中获取线程执行结果的方法与技巧及其在前端开发中的应用探讨
    本文探讨了C++异步编程中获取线程执行结果的方法与技巧,并深入分析了这些技术在前端开发中的应用。通过对比不同的异步编程模型,本文详细介绍了如何高效地处理多线程任务,确保程序的稳定性和性能。同时,文章还结合实际案例,展示了这些方法在前端异步编程中的具体实现和优化策略。 ... [详细]
  • 本文详细介绍了一种利用 ESP8266 01S 模块构建 Web 服务器的成功实践方案。通过具体的代码示例和详细的步骤说明,帮助读者快速掌握该模块的使用方法。在疫情期间,作者重新审视并研究了这一未被充分利用的模块,最终成功实现了 Web 服务器的功能。本文不仅提供了完整的代码实现,还涵盖了调试过程中遇到的常见问题及其解决方法,为初学者提供了宝贵的参考。 ... [详细]
  • 重要知识点有:函数参数默许值、盈余参数、扩大运算符、new.target属性、块级函数、箭头函数以及尾挪用优化《深切明白ES6》笔记目次函数的默许参数在ES5中,我们给函数传参数, ... [详细]
  • 本文总结了一些开发中常见的问题及其解决方案,包括特性过滤器的使用、NuGet程序集版本冲突、线程存储、溢出检查、ThreadPool的最大线程数设置、Redis使用中的问题以及Task.Result和Task.GetAwaiter().GetResult()的区别。 ... [详细]
  • 本地存储组件实现对IE低版本浏览器的兼容性支持 ... [详细]
  • 本文介绍了如何利用 `matplotlib` 库中的 `FuncAnimation` 类将 Python 中的动态图像保存为视频文件。通过详细解释 `FuncAnimation` 类的参数和方法,文章提供了多种实用技巧,帮助用户高效地生成高质量的动态图像视频。此外,还探讨了不同视频编码器的选择及其对输出文件质量的影响,为读者提供了全面的技术指导。 ... [详细]
  • 在PHP中如何正确调用JavaScript变量及定义PHP变量的方法详解 ... [详细]
  • 本文详细解析了一种实用的函数,用于从URL中提取查询参数。该函数通过处理URL中的搜索部分,能够高效地获取并解析出所需的参数值,适用于各种Web开发场景。 ... [详细]
  • 如何使用 `org.eclipse.rdf4j.query.impl.MapBindingSet.getValue()` 方法及其代码示例详解 ... [详细]
  • 本文详细解析了使用C++实现的键盘输入记录程序的源代码,该程序在Windows应用程序开发中具有很高的实用价值。键盘记录功能不仅在远程控制软件中广泛应用,还为开发者提供了强大的调试和监控工具。通过具体实例,本文深入探讨了C++键盘记录程序的设计与实现,适合需要相关技术的开发者参考。 ... [详细]
  • 本文介绍了如何利用Shell脚本高效地部署MHA(MySQL High Availability)高可用集群。通过详细的脚本编写和配置示例,展示了自动化部署过程中的关键步骤和注意事项。该方法不仅简化了集群的部署流程,还提高了系统的稳定性和可用性。 ... [详细]
  • Java Socket 关键参数详解与优化建议
    Java Socket 的 API 虽然被广泛使用,但其关键参数的用途却鲜为人知。本文详细解析了 Java Socket 中的重要参数,如 backlog 参数,它用于控制服务器等待连接请求的队列长度。此外,还探讨了其他参数如 SO_TIMEOUT、SO_REUSEADDR 等的配置方法及其对性能的影响,并提供了优化建议,帮助开发者提升网络通信的稳定性和效率。 ... [详细]
author-avatar
荣媛厉4
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有