理解 JavaScript 中的延迟加载
作者:Alexander Nnakwue✏️
介绍
在本文中,我们将探讨 Web 上的延迟加载机制。我们将介绍原生延迟加载 API、延迟加载的实现方式、延迟加载的重要性和优势,以及一个 Web 内容延迟加载的简单用例。为了顺利学习本教程,我们假设读者对使用 JavaScript 构建 Web 应用程序有基本的了解。
了解延迟加载 API 及其工作原理,将帮助那些已经使用过实现这些技术的库和框架的开发者理解其底层原理。此外,如果他们打算实现自己的延迟加载库,他们将能够进行更有指导性的研究,并运用所学的技术。
就现实世界的用例而言,通过其平台上的广告获得收入的营销和广告公司可以轻松优化和应用延迟加载,以便轻松判断访问其平台的用户看到了哪些广告,从而做出更好的商业决策。
什么是延迟加载?
根据维基百科,延迟加载是一种旨在推迟元素或对象初始化直至需要时才进行初始化的模式。这意味着,相对于父 DOM 元素,目标 DOM 元素仅在用户滚动浏览网页时才会加载并可见(当两个元素之间存在交集时,基于设定的阈值)。
不采用这种模式的缺点可能导致:
- 由于多个同步网络请求或批量请求从一个或多个来源获取一些图像或其他 Web 资源,导致页面性能严重滞后
- 由于需要下载/获取的包的大小,导致页面加载时间增加
- 用户留存率低,主要适用于网络连接较差的地区。由于我们开发者犯了早期没有实现延迟加载的错误,用户完全放弃某个平台的情况并不少见。
- 由于图像、iframe 和视频等资源或资产处理不当,会对 Web 性能和可访问性造成巨大影响
目前,大多数现代和更新的浏览器都原生支持延迟加载。但是,对于尚未提供此支持的浏览器,实现此技术的 polyfill 或库会在其上提供简单的 API 层。
延迟加载解决了减少初始页面加载时间的问题——仅显示用户在初始化网页和随后滚动页面时需要查看的图像或其他内容等资源。
众所周知,Web 性能和可访问性问题是多方面的;减少页面大小、内存占用和总体加载时间可以对 Web 平台做出巨大贡献。当我们有大量图片和视频,并在浏览器 DOM 初始化时一次性加载它们时,延迟加载的优势就变得显而易见。当然,正如我们之前讨论过的,您现在应该已经了解这将带来什么。
从数据来看,大多数网站严重依赖图片和其他网页内容(例如视频或 iframe)向目标受众传递信息。虽然这看似简单,但我们向用户展示这些内容的方式最终决定了我们平台的性能。
此外,一些有助于优化页面加载时间的操作,例如依赖于用户是否滚动到网页特定部分的事件,都是延迟加载的一些用例。随着本文的继续,我们将了解更多实际环境中的其他用例。
原生延迟加载 API
延迟加载建立在 Intersection Observer API 之上,这是一个浏览器 API,它提供了一种检测或了解何时称为目标、父元素的元素在浏览器视口内可用或可见的方法(视情况而定)。
当这种情况发生时,会调用一个处理函数来帮助处理代码逻辑的其他部分,我们稍后会看到。借助这个全新改进的浏览器 API,我们还可以知道两个 DOM 元素何时相交——我们指的是目标 DOM 元素何时进入浏览器的视口或与另一个元素(很可能是其父元素)相交。
为了更好地理解延迟加载的工作原理,我们首先必须了解如何创建交叉点观察器。要创建交叉点观察器,我们需要做的就是监听交叉点观察器事件的发生,并在此类事件发生时触发回调函数或处理程序。交叉点观察器事件是一种浏览器事件,与包含该DOMContentLoaded
事件的文档事件类别非常相似。
注意:对于交集事件,我们需要指定要应用交集的元素。该元素通常称为根元素。但是,如果未指定根元素,则表示我们打算将整个浏览器视口作为目标。
此外,我们还需要为根元素指定一个边距(如果提供),以便我们可以在必要时轻松更改其形状或大小。让我们看一个例子来更好地理解它:
let options = {
root: null,
rootMargin: 10px,
threshold: 1.0
}
let observer = new IntersectionObserver (options, callback);
在上面的代码片段中,我们看到了创建观察者的简单用例。该options
对象帮助我们为目标定义自定义属性。
这里,对象中的 threshold 属性options
表示何时触发回调。它的默认值为零,这意味着只要用户接近目标元素并且该元素变为可见,就会触发回调。
另一方面,root
是当目标元素在用户滚动网页时对用户可见时,充当目标元素视口的父元素。请注意,如果root
设置为 null,则父元素将自动成为视口。
最后,rootMargin
有助于设置根元素周围的边距。例如,在计算目标与父元素/视口之间的交集之前,我们可能需要调整其大小、边距或尺寸。
此外,回调接受两个输入参数,其中包括intersectionObserverEntry
我们打算应用于目标元素的对象列表以及调用回调的观察者。
回调的签名如下所示:
let callback = (entries, observer) => {
entries.forEach(entry => {
If (entry.isIntersection) {
// do some magic here
}
// and some other methods
})
}
该intersectionObserverEntry
对象表示父元素与目标元素之间存在交集。它的 API 中包含一系列属性,包括isIntersection
、intersectionRatio
、intersectionRect
、target
、time
等。有关这些属性的详细说明,请参阅MDN 文档的此部分。
我们需要定位一个特定的 DOM 元素,并在其与父元素相交时触发回调函数。以下代码片段展示了一个要定位的 DOM 元素示例:
let target = document.querySelector("#targetElement");
在上面的代码片段中,我们创建了一个目标元素并为其分配了一个变量。之后,我们使用构造函数/函数签名上的observe方法来观察目标元素intersectionObserver
,如下所示:
// start observing for changes on the target element
observer.observe(target);
当达到观察者为目标设置的阈值时,就会触发回调。很简单,对吧?
最后,该observe()
方法告诉观察者要观察哪个目标元素。需要注意的是,交叉点观察者的 API 中同样包含许多方法:例如unObserve()
,takeRecords()
、observe()
、 等等。
延迟加载技术的优点
现在,我们应该对为什么延迟加载 Web 内容和资源的必要性有了更好的理解。让我们看看使用此技术的其他一些优点:
- 构建高度可访问的 Web 应用程序。如今,Web 可访问性已成为热门话题。使用这项技术无疑有助于构建一个覆盖范围更广的平台。
- 高用户留存率。如果一个 Web 平台致力于推动业务目标,并进而提供价值,那么实施这项技术将极大地提升平台的用户友好度。Web 标准日后会感谢你的!
- 作为一名开发者,你可能需要在 Web 平台上实现无限滚动。理解这个概念将大有帮助,从而带来直接的商业价值。
实现延迟加载
让我们看一个网页上图片延迟加载的简单示例。首先,我们将自定义一个options
对象,用于观察与目标元素的交集:
let options = {
root: document.querySelector('.root'),
rootMargin: '0px, 0px, 100px, 0px'
};
现在,对于目标元素,让我们定位几个图像:
let images = [...document.querySelectorAll('.targetImages')];
现在,让我们看看如何实现回调:
const callback = (entries) => {
entries.forEach(entry => {
If (entry.isIntersecting) {
observer.unObserve('entry.target');
}
// handle other code logic here
})
}
我们可以继续调用交集观察器构造函数,根据其options
对象中指定的自定义来观察目标元素:
let observer = new intersectionObserver(options, callback);
最后,我们可以观察要观察的目标元素:
images.forEach(image => {
observer.observe(image);
})
注意:为了简单起见,这里没有包含 HTML 和 CSS 代码。您可以通过查看MDN 文档中的这个示例来详细了解如何实现此技术。
概括
现在,当我们在网页上有大量图片或视频,并在浏览器 DOM 初始化时将它们一起加载时,这项技术的优势应该显而易见。作为开发者,我们有责任确保所管理或维护的平台拥有最佳性能,尤其是在这些平台与业务目标紧密相关的情况下。延迟加载作为一种 Web 性能技术,有助于解决此类问题。
编者注:觉得这篇文章有什么问题?您可以在这里找到正确版本。
插件:LogRocket,一个用于 Web 应用的 DVR
LogRocket是一款前端日志工具,可让您重播问题,就像它们发生在您自己的浏览器中一样。无需猜测错误发生的原因,也无需要求用户提供屏幕截图和日志转储,LogRocket 让您重播会话,快速了解问题所在。它可与任何应用程序完美兼容,不受框架限制,并且提供插件来记录来自 Redux、Vuex 和 @ngrx/store 的额外上下文。
除了记录 Redux 操作和状态外,LogRocket 还记录控制台日志、JavaScript 错误、堆栈跟踪、带有标头 + 正文的网络请求/响应、浏览器元数据以及自定义日志。它还会对 DOM 进行插桩,以记录页面上的 HTML 和 CSS,即使是最复杂的单页应用程序,也能重现像素完美的视频。
免费试用。
文章《理解 JavaScript 中的延迟加载》首先出现在LogRocket 博客上。
鏂囩珷鏉ユ簮锛�https://dev.to/bnevilleoneill/understanding-lazy-loading-in-javascript-4f94