使用 intersection observer 延迟加载图片

使用 intersection observer 延迟加载图片

如果您还没有看过,Paul Lewis 组织了一个令人敬畏的视频系列,演示如何构建媒体播放器以及拥有非常棒的特性的 Progressive Web Apps。他在YouTube上建立了一系列视频,这些视频是在他建立网站的每一部分的过程中发生的。观看开发者展示他们工作的视频绝对是我最喜欢学习新事物的方法之一!

当他在演示他的代码时,我注意到他创建了一个出色的 helper 库来延迟加载图像。我一直在寻找改善我网站性能的方法,这无疑引起了我的兴趣。

与懒惰加载有什么关系?

延迟加载图像背后的想法是,您等到用户向下滚动页面,并图像进入视图之前,再为这个图片发起网络请求。如果您的网页包含多个图像,但是只有在图像滚动到视图时才加载每个图像,您将最终节省带宽,并确保您的网页加载更快。

为了给你一个这样的想法,我们来想象下面有三个图像的页面。

https://307a6ed092846b809be7-9cfa4cf7c673a59966ad8296f4c88804.ssl.cf3.rackcdn.com/intersection-observer/intersection-observer.png

如果用户登陆页面并且仅查看第一张图像,我们不想加载页面底部比萨的图像,直到用户向下滚动,并且等到图像真正在视图中。如果我们懒惰加载图像,这意味着用户只需要下载他们需要的东西,这使您的网页更精简。

对于更有经验的开发人员,您可能会熟悉延迟加载图像,毕竟这个概念已经有一段时间了。那么有什么新概念吗?!有很多懒加载库做得很好。我甚至以前在这个博客上写了一篇(很多年前)。问题在于,几乎所有这些库都会绑定滚动事件,或者使用定时器来检查元素的边界,然后再确定是否在视图中。这种方法的问题是它强制浏览器重新布局(re-layout)整个页面,并且在某些情况下,您的网站会引起相当大的性能损失。我们可以做得更好!

INTERSECTION OBSERVER 来抢救!

这是就是 Intersection Observer 的用处。Intersection Observer 内置于大多数现代浏览器中,让您知道被观察的元素何时进入或退出浏览器的视口。这使得它非常理想,因为它能够异步传输数据,并且不会影响主线程,使其成为提供反馈的有效手段。

Paul 的例子中,他演示了如何使用 Intersection Observer 来延迟加载进入视口图像。我已经获取了他的初始代码,并稍微调整了一点,使我更容易理解。在本文中,我将通过了解 Intersection Observer 的基础知识,并向您展示如何以超级高效的方式做到延迟加载图像。

入门

想象一下一个基本的HTML页面,其中包含三个与上述相似的图像。在网页上,您将具有与以下熟悉的图像元素代码:


您可能会注意到,在上面的代码中,图像文件没有 src 属性。这是因为它正在使用一个名为 data-src 的数据属性来指向图像源。当进入视口时,我们将使用它来加载图像。您还可能会注意到,图像元素还具有一个名为 “js-lazy-image” 的类 - 我们将在 JavaScript 代码中尽快使用这个类,以确定要延迟加载的元素。

接下来,我们需要创建将在页面上加载图像的代码。在我们的 JavaScript 文件中,我们需要创建一个新的 Intersection Observer 。

上面的例子看起来像很多代码,但是让我们一步一步地分解它。首先,我正在选择页面上具有类“js-lazy-image”的所有图像。接下来,我正在创建一个新的 IntersectionObserver,并使用它来观察我们选择的具有类“js-lazy-image”的所有图像。使用 IntersectionObserver 的默认选项,当元素部分进入视图或完全离开视口时,您的回调都将被调用。在这种情况下,我将几个额外的配置选项传递给 IntersectionObserver。使用 rootMargin 允许您指定根的边距,有效地允许您增加或缩小用于观察交点的区域。我们想确保如果图像在Y轴上的50像素内,我们将开始下载。

现在我们已经创建了一个 Intersection Observer,并且正在观察页面上的图像,我们可以进入到该元素进入视图时被触发的 intersection 事件。

在上面的代码中,只要我们观察到的元素进入用户视口,onIntersection 功能将被触发。此时,我们可以循环查看我们观察到的图像,并确定哪个图像在视口中。如果当前元素处于交叉比例中,我们知道图像在用户视口中,我们可以加载它。加载图像后,我们不需要再观察图像,并且使用 unobserve() 将其从 Intersection Observer 中的条目列表中删除。

就是这样!一旦用户滚动并且图像进入视图,则将加载适当的图像。这个代码最好的办法是 Intersection Observer 比巴里·怀特(Barry White)更平滑。我尽量保持尽可能简洁的代码,但如果您想看到完整版本,我已经创建了一个Github repo,其中包含了一个有效的例子

浏览器支持

在这一点上,您可能会想知道浏览器对此功能的支持。Edge,Firefox,Chrome和Opera目前支持 Intersection Observer,这是一个好消息。

但是,为了确保不支持此功能的浏览器的代码不会报错,我们可以使用功能检测来确定我们如何加载图像。我们来看看下面的代码。

在上面的代码中,我们正在检查 IntersectionObserver 是否在当前浏览器中可用,如果不支持我们只是简单地立即加载图像,否则我们使用我们的默认行为。

如果您真的喜欢 IntersectionObserver API 的简便性,并且想要使用 polyfill,则 WICG 已创建一个可在 Github repository 中使用的功能。唯一的缺点是您不会获得原生实现给您的性能优势。

您甚至可以采取进一步措施,并为 Robin Osborne 建议的未启用 JavaScript 的用户添加支持。

总结

在本文中,我们已经使用 IntersectionObserver 来延迟加载图像,但是您可以使用它来进行更多操作。它可以用于确定某人是否正在查看广告,或者即使是在iFrame中的元素。易于理解的API使其可以打开许多选项。

如果您想了解有关交叉点观察者的更多信息,我建议您在Google Developers网站上阅读这篇有关信息的文章。我还强烈建议在 Youtube 上观看保罗·刘易斯的视频系列,它包含了很棒的提示,你一定会学到一些东西。

【翻译原文】: LAZY LOADING IMAGES USING INTERSECTION OBSERVER

0%