惰性加载网页上的图片资源 1

惰性加载网页上的图片资源

惰性顾名思义就是懒惰,何为懒惰,就是那种你不命令,它就坐定定响度,企定定响度,咩都唔使做。

回到页面上,懒加载就是指,当图片元素不在屏幕上浏览器可见区域内或周围,就不需要进行 HTTP 请求进行加载。

这有什么好处呢,好处就是在一定程度上帮你节省了流量,避免不必要的浪费,而且浏览器请求有数量限制,假如图片太大太多会阻塞一部分 HTTP 的请求(当然这个发起顺序有关),而且请求太多图片且图片很大的情况下,页面会略显丢丢卡顿。

1. <img> loading 属性

Chrome 浏览器原生上直接就支持,最近我看了 Firefox 上好像也支持了,可谓是幸事一件,毕竟最近换了主力浏览器为 Firefox 。

Can I Use Loading
数据来自 Can I Use

但在 Can I Use 网站的数据了解到,Firefox 是部分支持的,但不支持 iFrames。Chrome,Edge,Opera 等原谅绿全支持。唯独 Safair 全平台不支持,一片大红,但从下面的备注 2 了解到,Safair 是可以在设置里面开启使用的,但又有多少个正常使用者会知道而且去开启呢。

但既然大部分支持,那就使用吧,反正也是不碍的,先占个位。

基本属性值

loading 属性总共有三种 values 供选择,分别是

  • lazy : 不加载可视区域外的图片,进入可视区内域或某个阀值周围时进行加载
  • eager : 不管图片元素在不在可视区域都加载
  • auto : 可能是 lazyeager,浏览器自行决定

使用方式

<img src="image-url" loading="lazy" alt="延迟加载" />
<img src="image-url" loading="eager" alt="立即加载" />
<img src="image-url" loading="auto" alt="浏览器自行判断" />

2. 使用 JavaScript

使用 JavaScript 进行进行图片 Lazy Loading,主要做以下这几件事:

  • 不让图片资源正常发起加载
  • 监视图片元素,判断是否进入了可视区域
  • 进入可视区域,进行发起资源请求

我看见过某些网页也会使用 JavaScript 进行实现,大致手段与我无疑异,它们会使用 src 占位图搭配自定义属性 data-src 真实图片地址来实现。 如:

<img src="placeholder.png" data-src="real-img.png" />

实现懒加载的几种方法

最简单莫过与使用别人已经写好的插件,这里可以使用 lazyload.js 这个小插件,其次是 Intersection Observer API,最次是第一种方法,各种监听计算量很大,对性能不太好,但可以搭配防抖和节流进行限制频率。

Intersection Observer API

<script>
    !function () {
        function isSupportLoading() {
            return 'loading' in HTMLImageElement.prototype;
        }

        window.addEventListener('DOMContentLoaded', function (event) {

            var images = document.querySelectorAll("img[loading='lazy']");
            if (images.length === 0) return; //没图片啥也不用干

            if (isSupportLoading()) {
                images.forEach(function (img) {
                    img.src = img.getAttribute('dat-src');
                })

                return;
            }

            var observerInstance = new IntersectionObserver(function (entries, observerInstance) {
                for (let entry of entries) {
                    if (entry.isIntersecting) {
                        imgElelement = entry.target
                        imgElelement.setAttribute('src', imgElelement.getAttribute('data-src'));
                        observerInstance.unobserve(entry.target)
                    }
                }
            });

            images.forEach(function (img) {
                var src = img.getAttribute('src')
                if (src != null && src.length > 0) {
                    img.setAttribute('data-src', src)
                    img.removeAttribute('src');
                }

                var srcset = img.getAttribute('srcset')
                if (srcset != null && srcset.length > 0) {
                    img.setAttribute('data-srcset', srcset)
                    img.removeAttribute('srcset');
                }

                observerInstance.observe(img)
            })
        })
    }()
</script>

我们在 12 行先判断是否支持原生 loading, 如果支持那么直接把 src 换成 data-src, 假如不支持,在 20 行 new 了一个 IntersectionObserver 构造函数,并传入一个函数作为第一个参数,new IntersectionObserver 返回一个观察器实例,该实例有一个 observe 方法,该方法接收一个 DOM 节点, 对该 DOM 进行观察。

我们在 43 行 给每个 img 进行观察。如果该 DOM 可见性发生变化,就会执行 new IntersectionObserver 时传递的一个方法,该回掉方法的第一个参数 entries 是一个数组,如果同时有多被观察 DOM 可见性发生变化,该数组就包含多个成员,每个成员是 IntersectionObserverEntry 对象,这个对象的 target 就是 <img> 元素自身,成员对象的 isIntersecting 属性代表是否进入可视区域是否可见,发生变化有两种情况,进入和离开。如果进入 isIntersecting 为 true 代表进入,那么我们就可以进行对 <img> 的 src 值 设为 data-src 的值。

虽然我们已经换了 src 值,意味我们已经不需要对已经加载了图片资源的元素进行观察,我们可以使用实例的 unobserve 方法进行取消观察,节省了不必要的开销。

当然觉得麻烦,可以直接使用插件,用就完事了,我也是使用插件 惰性加载网页上的图片资源 2惰性加载网页上的图片资源 2惰性加载网页上的图片资源 2

结束语

写到口渴,下去小卖部买个冰可乐解解渴 ~,可乐真是字如起名,每次喝可乐我都感到很快乐,人世间最快乐的事也莫过于此,气泡在舌尖炸开,酥麻感沁透心脾,琥珀色的液体竟有如此魔力,夏天和可乐真配。

惰性加载网页上的图片资源 5
啊~~~爽透心凉

交流,但不求共鸣

    我要留言

    Tips: 支持匿名免邮留言。填写邮箱地址有利于对各位靓仔/靓女进行消息通知。留言头像服务来自Gravatar

    留言者基本信息 匿名訪客
    匿名訪客
    留言主要内容
    Sticker Heo on wordpress, Get !!!!
    Kaomojis 颜字

    Σ(っ °Д °;)っ  惊吓w(゚Д゚)w  啊啊(°ཀ°)  吐血(⊙﹏⊙)  呃呃呃o(≧口≦)o  崩溃(´•︵•`)  难过(;´༎ຶД༎ຶ`)  哭死→_→  斜眼看( ̄_, ̄ )  不屑( *︾▽︾)  陶醉(* ̄3 ̄)╭  飞吻o( ̄┰ ̄*)ゞ  不好意思(。・_・。)ノ  对不起φ(≧ω≦*)♪  乐(*^▽^*)  开心(๑╹◡╹)ノ  高兴*´∀`)´∀`)*´∀`)*´∀`)  哈哈哈哈ヽ(✿゚▽゚)ノ  好耶(๑•̀ㅂ•́)و✧  棒Ψ( ̄∀ ̄)Ψ  美味

    验证码加载中....

    BACK TO TOP