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

图像延迟加载列表图顺序加载

图片延时加载十分重要,尤其是对于移动端用户。从理论上来看,图像延迟加载机制十分简单,但实际上却有很多需要注意的细节。此外,有

图片延时加载十分重要,尤其是对于移动端用户。

从理论上来看,图像延迟加载机制十分简单,但实际上却有很多需要注意的细节。 此外,有多个不同的用例均受益于延迟加载。 首先,我们来了解一下在 HTML 中延迟加载内联图像。

延迟加载是一种在加载页面时,延迟加载非关键资源的方法, 而这些非关键资源则在需要时才进行加载。 就图像而言,“非关键”通常是指“屏幕外”。

最近在做一个移动端漫画应用(id.mangaya.mobi),涉及的图片比较多,如果图片不做额外处理,会对用户不太友好,而且lighthouse评分也会因此降低。

场景

主要有两种场景。

有兴趣的同学可以查看react-progressive-lazy-image,使用起来非常简单!

Senario 1: 图片延时到在窗口viewport内才开始加载。

Senario 2: 用户观看漫画,需要漫画一张张的顺序加载。

原理

图片懒加载技术主要通过监听图片资源容器是否出现在视口区域内,来决定图片资源是否被加载。

那么实现图片懒加载技术的核心就是如何判断元素处于视口区域之内。

实践

那么如何实现呢?

getBoundingClientRect()

返回的值是一个DOMRect对象,它是getClientRects()元素返回的矩形的并集,即与元素关联的CSS边框。其结果是,其包含整个元件,具有只读的最小矩形left,top,right,bottom,x,y,width,和height性质描述在像素整体边界框。除视口左上角width和height相对于视口左上角的属性。

下面代码可以判断元素是否在窗口内

//https://gomakethings.com/how-to-test-if-an-element-is-in-the-viewport-with-vanilla-Javascript/
export const elementIsInsideViewport &#61; el &#61;> {const bounding &#61; el.getBoundingClientRect();return (bounding.top >&#61; 0 &&bounding.left >&#61; 0 &&bounding.bottom <&#61;(window.innerHeight || document.documentElement.clientHeight) &&bounding.right <&#61;(window.innerWidth || document.documentElement.clientWidth));
};

可以结合window.onScroll以及window.onResize事件以及throttle来实现对img元素的判断。

document.addEventListener("DOMContentLoaded", function() {let lazyImages &#61; [].slice.call(document.querySelectorAll("img.lazy"));let active &#61; false;const lazyLoad &#61; function() {if (active &#61;&#61;&#61; false) {active &#61; true;setTimeout(function() {lazyImages.forEach(function(lazyImage) {if ((lazyImage.getBoundingClientRect().top <&#61; window.innerHeight && lazyImage.getBoundingClientRect().bottom >&#61; 0) && getComputedStyle(lazyImage).display !&#61;&#61; "none") {lazyImage.src &#61; lazyImage.dataset.src;lazyImage.srcset &#61; lazyImage.dataset.srcset;lazyImage.classList.remove("lazy");lazyImages &#61; lazyImages.filter(function(image) {return image !&#61;&#61; lazyImage;});if (lazyImages.length &#61;&#61;&#61; 0) {document.removeEventListener("scroll", lazyLoad);window.removeEventListener("resize", lazyLoad);window.removeEventListener("orientationchange", lazyLoad);}}});active &#61; false;}, 200);}};document.addEventListener("scroll", lazyLoad);window.addEventListener("resize", lazyLoad);window.addEventListener("orientationchange", lazyLoad);
});

此代码在 scroll 事件处理程序中使用 getBoundingClientRect 来检查是否有任何 img.lazy 元素处于视口中。 使用 setTimeout 调用来延迟处理&#xff0c;active 变量则包含处理状态&#xff0c;用于限制函数调用。 延迟加载图像时&#xff0c;这些元素随即从元素数组中移除。 当元素数组的 length 达到 0 时&#xff0c;滚动事件处理程序代码随即移除。

虽然此代码几乎可在任何浏览器中正常运行&#xff0c;但却存在潜在的性能问题&#xff0c;即重复的 setTimeout 调用可能纯属浪费&#xff0c;即使其中的代码受限制&#xff0c;它们仍会运行。 在此示例中&#xff0c;当文档滚动或窗口调整大小时&#xff0c;不管视口中是否有图像&#xff0c;每 200 毫秒都会运行一次检查。 此外&#xff0c;跟踪尚未延迟加载的元素数量&#xff0c;以及取消绑定滚动事件处理程序的繁琐工作将由开发者来完成。

最佳实践 使用 Intersection Observer

此方法非常简单&#xff0c;只需要为元素生成一个IntersectionObserver,并且监听该元素&#xff0c;然后在监听的回调判断元素的intersectionRatio比率即可达到所需。这是核心代码.

componentDidMount() {const { src, needLazyUtilInViewPort, canLoadRightNow } &#61; this.props;if (needLazyUtilInViewPort) {//https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_APItry {const node &#61; ReactDOM.findDOMNode(this);this.observer &#61; new IntersectionObserver(this.insideViewportCb);this.observer.observe(node);} catch (err) {console.log("err in finding node", err);}} else {if (canLoadRightNow) {this.loadImage(src);}}}insideViewportCb(entries) {entries.forEach(element &#61;> {//在viewport里面if (element.intersectionRatio >0) {this.loadImage(this.props.src);}});}

不过&#xff0c;Intersection Observer 的缺点是虽然在浏览器之间获得良好的支持&#xff0c;但并非所有浏览器皆提供支持。 对于不支持 Intersection Observer 的浏览器&#xff0c;您可以使用 polyfill&#xff0c;或者如以上代码所述&#xff0c;检测 Intersection Observer 是否可用&#xff0c;并在其不可用时回退到兼容性更好的旧方法。

至于列表图顺序加载的话&#xff0c;只需要在每个图片回调通知父组件可以加载下一张就可以了。 总的来说getBoundingClientRect和Intersection Observer都可以实现图片懒加载&#xff0c;但是getBoundingClientRect如果在当前页面使用到其他onScroll事件&#xff0c;会出现卡顿等问题&#xff0c;不能非常顺畅的滑动&#xff0c;而Intersection Observer使用起来非常简单流畅。

图像延迟加载 && 列表图顺序加载的组件已经开源啦&#xff5e;&#xff01;

有兴趣的同学可以查看react-progressive-lazy-image,使用起来非常简单&#xff01;



推荐阅读
  • 从零基础到精通的前台学习路线
    随着互联网的发展,前台开发工程师成为市场上非常抢手的人才。本文介绍了从零基础到精通前台开发的学习路线,包括学习HTML、CSS、JavaScript等基础知识和常用工具的使用。通过循序渐进的学习,可以掌握前台开发的基本技能,并有能力找到一份月薪8000以上的工作。 ... [详细]
  • 在Android开发中,使用Picasso库可以实现对网络图片的等比例缩放。本文介绍了使用Picasso库进行图片缩放的方法,并提供了具体的代码实现。通过获取图片的宽高,计算目标宽度和高度,并创建新图实现等比例缩放。 ... [详细]
  • Android中高级面试必知必会,积累总结
    本文介绍了Android中高级面试的必知必会内容,并总结了相关经验。文章指出,如今的Android市场对开发人员的要求更高,需要更专业的人才。同时,文章还给出了针对Android岗位的职责和要求,并提供了简历突出的建议。 ... [详细]
  • CSS3选择器的使用方法详解,提高Web开发效率和精准度
    本文详细介绍了CSS3新增的选择器方法,包括属性选择器的使用。通过CSS3选择器,可以提高Web开发的效率和精准度,使得查找元素更加方便和快捷。同时,本文还对属性选择器的各种用法进行了详细解释,并给出了相应的代码示例。通过学习本文,读者可以更好地掌握CSS3选择器的使用方法,提升自己的Web开发能力。 ... [详细]
  • 本文介绍了OC学习笔记中的@property和@synthesize,包括属性的定义和合成的使用方法。通过示例代码详细讲解了@property和@synthesize的作用和用法。 ... [详细]
  • javascript  – 概述在Firefox上无法正常工作
    我试图提出一些自定义大纲,以达到一些Web可访问性建议.但我不能用Firefox制作.这就是它在Chrome上的外观:而那个图标实际上是一个锚点.在Firefox上,它只概述了整个 ... [详细]
  • Google Play推出全新的应用内评价API,帮助开发者获取更多优质用户反馈。用户每天在Google Play上发表数百万条评论,这有助于开发者了解用户喜好和改进需求。开发者可以选择在适当的时间请求用户撰写评论,以获得全面而有用的反馈。全新应用内评价功能让用户无需返回应用详情页面即可发表评论,提升用户体验。 ... [详细]
  • 原文地址:https:www.cnblogs.combaoyipSpringBoot_YML.html1.在springboot中,有两种配置文件,一种 ... [详细]
  • 本文主要解析了Open judge C16H问题中涉及到的Magical Balls的快速幂和逆元算法,并给出了问题的解析和解决方法。详细介绍了问题的背景和规则,并给出了相应的算法解析和实现步骤。通过本文的解析,读者可以更好地理解和解决Open judge C16H问题中的Magical Balls部分。 ... [详细]
  • 20211101CleverTap参与度和分析工具功能平台学习/实践
    1.应用场景主要用于学习CleverTap的使用,该平台主要用于客户保留与参与平台.为客户提供价值.这里接触到的原因,是目前公司用到该平台的服务~2.学习操作 ... [详细]
  • 解决VS写C#项目导入MySQL数据源报错“You have a usable connection already”问题的正确方法
    本文介绍了在VS写C#项目导入MySQL数据源时出现报错“You have a usable connection already”的问题,并给出了正确的解决方法。详细描述了问题的出现情况和报错信息,并提供了解决该问题的步骤和注意事项。 ... [详细]
  • 拥抱Android Design Support Library新变化(导航视图、悬浮ActionBar)
    转载请注明明桑AndroidAndroid5.0Loollipop作为Android最重要的版本之一,为我们带来了全新的界面风格和设计语言。看起来很受欢迎࿰ ... [详细]
  • 自动轮播,反转播放的ViewPagerAdapter的使用方法和效果展示
    本文介绍了如何使用自动轮播、反转播放的ViewPagerAdapter,并展示了其效果。该ViewPagerAdapter支持无限循环、触摸暂停、切换缩放等功能。同时提供了使用GIF.gif的示例和github地址。通过LoopFragmentPagerAdapter类的getActualCount、getActualItem和getActualPagerTitle方法可以实现自定义的循环效果和标题展示。 ... [详细]
  • 本文详细介绍了MySQL表分区的创建、增加和删除方法,包括查看分区数据量和全库数据量的方法。欢迎大家阅读并给予点评。 ... [详细]
  • 猜字母游戏
    猜字母游戏猜字母游戏——设计数据结构猜字母游戏——设计程序结构猜字母游戏——实现字母生成方法猜字母游戏——实现字母检测方法猜字母游戏——实现主方法1猜字母游戏——设计数据结构1.1 ... [详细]
author-avatar
都市养生堂
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有