使用 JavaScript 延迟加载图像的工作原理是啥?

Posted

技术标签:

【中文标题】使用 JavaScript 延迟加载图像的工作原理是啥?【英文标题】:How lazy loading images using JavaScript works?使用 JavaScript 延迟加载图像的工作原理是什么? 【发布时间】:2012-03-12 13:10:14 【问题描述】:

我很好奇延迟加载图像,即滚动到它们时将加载的图像的工作原理。

有什么提示吗?

【问题讨论】:

这能回答你的问题吗? How do you make images load only when they are in the viewport? 【参考方案1】:

这是使用插件的方法:http://www.webresourcesdepot.com/lazy-loading-of-images-resources-you-need/ 这是 jquery 插件:http://www.appelsiini.net/projects/lazyload

基本上你在src 属性中放置一个虚拟图像并为实际图像添加另一个属性,JS 检测页面的滚动位置,并在你足够接近图像时加载图像数据。它通过将src 替换为实际图像的源来实现。

这里有另一种解释:http://engineering.slideshare.net/2011/03/faster-page-loads-with-image-lazy-loading/

【讨论】:

【参考方案2】:

2020+ 解决方案:

有一种延迟加载图像的本机方法已经在某些浏览器中工作。虽然标准化仍在进行中,但您今天已经可以使用它!只需将loading 属性添加到您的图像标签并将其设置为“惰性”:

<img
    src="picture.jpg"
    
    
    
    loading="lazy"
>

就是这样。只要当前视口足够近,兼容的浏览器就会延迟加载该图像。

此处提供更多信息:

Native lazy-loading for the web Request to be added in the html specification Current browser support

如果您需要旧版浏览器的解决方案,您应该查看 MDN 上的 Lazy loading。

【讨论】:

这样的延迟加载有什么缺点吗?如果不是,不是每张图片都应该使用loading 属性吗? ***.com/questions/61314750/… 此解决方案目前不支持在 chrome 中打印,请参阅此bugreport。打印页面时,尚未加载的图像将在打印输出中丢失。【参考方案3】:

以及如何轻松做到这一点的示例。

<img src="/images/lazy.jpg" data-real-src="/images/company-1.jpg">

“lazy.jpg”可以用于所有图像,这将导致实际上只加载一张图像(这是一个 1x1 像素的小重量图像)。所以,考虑一下我有一个要访问的 250 家商店的列表,每个商店都有一个公司徽标。可能看起来像这样:

<img src="/images/lazy.jpg" data-real-src="/images/company-1.jpg">
<img src="/images/lazy.jpg" data-real-src="/images/company-2.jpg">
<img src="/images/lazy.jpg" data-real-src="/images/company-3.jpg">
...

然后魔法来了! 把它放在你的 javascript 文件中:

$('img[src="/images/lazy.jpg"]').each(function(index, el) 
    $(el).attr('src', $(el).data('real-src'));
);

wacka-wacka,所有的lazy.jpg 图像都将被它们的“真实”图像替换。让您的 html 页面加载更快的目的(因为这 250 家公司在lazy.jpg 中都有相同的“徽标”:)...但是 JS 会在 DOM 完成加载后处理这一切。

这当然是一个 jQuery 解决方案。也可以用纯js来完成。

【讨论】:

【参考方案4】:

可以使用justlazy,它独立于jQuery等依赖,非常轻量级:

您需要的唯一电话是:

var placeholders = document.querySelectorAll(".load-if-visible");
for (var i = 0; i < placeholders.length; ++i) 
  Justlazy.registerLazyLoad(placeholders[i]);

占位符必须是以下结构:

<span data-src="url/to/image" data-
      data-title="some title" class="load-if-visible">
</span>

出于 SEO 原因,您可以使用任何其他占位符(例如占位符图片)。

此外,还有一个如何使用它的指南以及一些关于延迟加载图像的一般信息。

【讨论】:

【参考方案5】:

使用将侦听器附加到滚动事件或使用 setInterval 的传统方式延迟加载图像的性能非常低,因为每次调用 getBoundingClientRect() 都会强制浏览器 re-layout 整个页面,并且会给您的页面带来相当大的卡顿网站。

使用 Lozad.js(只有 569 字节,没有依赖关系),它使用 InteractionObserver 来高效地延迟加载图像。

【讨论】:

【参考方案6】:

浏览器级别的原生延迟加载终于可用了。

<img src="image.png" loading="lazy"   >

&lt;img loading=lazy&gt; 受到大多数流行的 Chromium 驱动的浏览器(Chrome、Edge、Opera)、Firefox 的支持,WebKit (Safari) 的实施正在进行中。 Can I use 有关于跨浏览器支持的详细信息。不支持加载属性的浏览器会直接忽略它而不会产生副作用。

Improved data-savings and distance-from-viewport thresholds

【讨论】:

【参考方案7】:

2021 - 保持简单...

这里有很多 插件 建议,根据您的用例,这些建议可能对您很有价值。

如果您懒得在下面编写这个简短的 sn-p 代码,或者您需要已经构建的回调,那么您可以使用我构建的这个插件,它基于这个确切的答案,缩小后只有 0.5kb。我的插件 Simply Lazy 甚至可以在 IE 上使用,如果您只需添加一个 polyfill。

最后,如果您只需要延迟加载一些图像,那么它很简单:

<img data-src="your-image-path-here" class="lazyload" />

还有:

let observer = new IntersectionObserver((entries, observer) => 
  entries.forEach(function (entry) 
    if (entry.intersectionRatio > 0 || entry.isIntersecting) 
      const image = entry.target;
      observer.unobserve(image);

      if (image.hasAttribute('src')) 
        // Image has been loaded already
        return;
      

      // Image has not been loaded so load it
      const sourceUrl = image.getAttribute('data-src');
      image.setAttribute('src', sourceUrl);

      image.onload = () => 
        // Do stuff
      

      // Removing the observer
      observer.unobserve(image);
    
  );
);

document.querySelectorAll('.lazyload').forEach((el) => 
  observer.observe(el);
);

使用Intersection Observer API 让这一切变得非常简单。您也可以在shadowRoot 中使用它,它在那里也可以正常工作。

我还发现这个article 有助于了解这里发生了什么。

【讨论】:

【参考方案8】:

有很多方法可以实现延迟加载。这个过程就是你加载你需要的东西。您可以延迟加载软件场景中的任何内容。在网站上,大多数在加载图像时都会使用它,这是因为大多数网站几乎只是图像。我的意思是网站的艺术作品加上他们可以在您的服务器上拥有数千张图片的真实人物图片。当您尝试同时加载所有这些文件时,这通常会导致速度变慢。在某些时候,它开始减慢这个过程。因此,延迟加载通常适用于大型网站。就像我说的那样,您可以通过多种方式做到这一点。已经给出了一种方法。已经加载了 img 标签,但 src 部分指向一个虚拟文件,它的大小很小。不要使用图形或图片的图像......使用像灰色块这样的东西......或者什么都不能使用。然后当滚动部分靠近图像附近的滚动点时。它将运行一个函数,它将用真实的图像链接替换 ​​src。另一种方法是使用 ajax 和关闭时的滚动点将追加...加载实际的 html 代码和 src 中的图像。这是我实际使用的。我编写了一个 php 文件来延迟加载图像、数据、文本。

此方法的重点是在需要时从网站下载文件。加载图像时,它实际上是从您的服务器下载的。因此,当您开始处理较大的图像文件和太多的图像文件时,下载过程和实际加载时间可能会增加。

【讨论】:

以上是关于使用 JavaScript 延迟加载图像的工作原理是啥?的主要内容,如果未能解决你的问题,请参考以下文章

通过 JavaScript 加载 SPDY 和延迟图像

javascript 防止从延迟加载的图像中恢复内容

javascript 基本图像延迟加载

如何在延迟加载期间在图像占位符上显示“加载”gif图像

使用 LazySizes 延迟加载轮播图像

SAP Spartacus 的延迟加载 Lazy load 设计原理