图片懒加载的五种方法

477 阅读3分钟

英文原文:www.sitepoint.com/five-techni…

1. 原生惰性加载

<img src="myimage.jpg" loading="lazy" alt="..." />

<iframe src="content.html" loading="lazy"></iframe>

正如你所看到的,没有JavaScript,没有src属性值的动态交换,只是普通的原始HTML。

loading属性使我们可以选择延迟视口外图像和iframe,直到用户滚动到它们的附近。

loading有三个值:

  • lazy:延迟加载
  • eager:立即加载
  • auto:浏览器决定是否延迟加载(默认)

兼容处理

<!-- Let's load this in-viewport image normally --> 
<img src="hero.jpg" alt=".."/> 
<!-- Let's lazy-load the rest of these images --> 
<img data-src="unicorn.jpg" loading="lazy" alt=".." class="lazyload"/> 
<img data-src="cats.jpg" loading="lazy" alt=".." class="lazyload"/> 
<img data-src="dogs.jpg" loading="lazy" alt=".." class="lazyload"/> 
<script> 
if ('loading' in HTMLImageElement.prototype) { 
    const images = document.querySelectorAll("img.lazyload"); 
    images.forEach(img => { img.src = img.dataset.src; }); 
 } else { 
 // Dynamically import the LazySizes library
     let script = document.createElement("script"); 
     script.async = true; 
     script.src = "https://cdnjs.cloudflare.com/ajax/libs/lazysizes/4.1.8/lazysizes.min.js"; 
     document.body.appendChild(script); 
 } 
 </script>

2. 使用Intersection Observer API实现懒加载

Intersection Observer是一个新的Api,我们可以利用它来延迟加载图片和其他内容。

<img data-src="image.jpg" alt="test image">

⚠注意:图片的路径是包含在data-src属性中的,而不是src属性中的。原因是使用src意味着图像会立即加载。

在CSS中,给每个图像一个最小的高度值,比如100px。这为每个图像占位符(不带src属性的img元素)提供一个垂直高度:


img {
  min-height: 100px;
  /* more styles here */
}

在JavaScript中,创建一个配置对象,并将其注册到IntersectionObserver实例中。

// 创建一个config对象: 对象上有rootMargin和threshold属性
const config = {
    rootMargin: '0px 0px 50px 0px',
    threshold: 0
}
// 注册这个config对象到IntersectionObserver实例
let observer = new intersectionObserver(function(entries, self) {
    // 遍历每个entry
    entries.foreach(entry => {
        if(entry.isIntersecting) {
            // 实现一个函数,将data-src属性上的路径复制到src属性上
            preloadImage(entry.target)
            // 图片已经替换了,就停止监听
            self.unobserve(entry.target)
        }
    })
})

最后,对所有图像进行迭代,并将它们添加到此迭代Observer实例中:

const imgs = document.querySelectorAll('[data-src]');
imgs.forEach(img => {
    observer.observe(img)
})

这种解决方案的优点是: 实施起来很容易,效果很好,而且让IntersectionObserver在计算方面承担了繁重的计算工作。

另一方面,尽管大多数浏览器在其最新版本中都支持IntersectionObserver API,但并非所有浏览器都一致支持它。幸运的是,可以使用polyfill。

3. Lozad.js

实现图片延迟加载的一个快速而简单的替代方案是让JS库为你完成大部分工作。

Lozad是一个高性能、轻量级和可配置的纯JavaScript惰性加载的库,没有依赖关系。你可以使用它来延迟加载图像、视频、iframe等,该库底层使用的是IntersectionObserver API实现。

首先,安装Lozad包

npm install --save lozad

其次,使用模块bundler引入它

import lozad from 'lozad'

或者,你也可以使用CDN简单的下载这个库,在页面底部使用<script>标签添加:

<script src="https://cdn.jsdelivr.net/npm/lozad/dist/lozad.min.js"></script>

接下来,是基本的实现,在你的<img>标签中增加class="lozad":

<img class="lozad" data-src="img.jpg" />

最后,在JS中实例化Lozad:

const observer = lozad();
observer.observe()

如果你不想深入研究IntersectionObserver API的工作原理,或者只是想寻找一种适合于各种内容类型的快速实现,Lozad是一个很好的选择。

只需注意浏览器的支持,并最终将此库与IntersectionObserver API的polyfill集成。

4. 具有模糊图像效果的延迟加载

你看到的图像是模糊、低分辨率副本,而它的高分辨率版本正在缓慢加载。

首先引入第三方库progressive-image:

<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/progressive-image.js/dist/progressive-image.css">
<script src="https://cdn.jsdelivr.net/npm/progressive-.js/dist/progressive-image.js" defer></script>

或者

npm i progressive-image.js

其次,添加一个<img>标签,带上class="preview",这个用于加载小图片。

然后,添加一个<a>标签包裹<img><a>标签带上class="progressive replace"><a>标签上的href是大图片的地址。


<a href="full.jpg" class="progressive replace">
  <img src="tiny.jpg" class="preview" alt="image" />
</a>

预览图像和全尺寸图像必须具有相同的纵横比,例如4030和800600。

其他功能参考下方链接:

www.sitepoint.com/how-to-buil…

github.com/craigbuckle…

codepen.io/craigbuckle…

5. Yall.js

github.com/malchata/ya… yall.js是一个SEO友好的惰性加载库,适用于<video>元素以及CSS背景图像。它适用于所有现代浏览器。他在可用的情况下使用IntersectionObserver。yall.js还使用Mutation Observer来监控DOM的更改。

yall.js 4 删除了<img><picture><iframe>元素的惰性加载,因为原生惰性加载覆盖了这些。然而,yall.js 4保留了延迟加载自动播放<video>(ala 动画 GIFS),延迟加载<video>元素海报图像以及CSS背景图像的能力。