document引用图片的src属性能干嘛_图片懒加载的几种方法

1634af6acaa911d064591c46f1ae8beb.png

在一些图片比较多的网站会用到 图片懒加载 技术,这项技术可以延迟加载图像,只当图片出现在我们看到的视图中才加载,它的好处是大大提高用户体验,节省不必要的资源浪费以及网站的性能提升等。下面介绍几种图片懒加载的方法,分别是监听 scroll、resize 事件,使用 Intersection Observer API 以及 Chrome70 自带的懒加载设置。任何技术都是为解决问题服务的。在开始之前,还是要了解清楚「是什么」以及「为什么」。

什么是懒加载

当一个网站的图片数量较多时,直接加载可能会有很大的开销,不利于性能,这时可以将所有的图片换成轻量的占位图,不加载图片。而当用户真正滚动到图片出现时,再迅速将占位图片换成真正我们想展示的图片,这整个过程就是懒加载。

为什么要懒加载

当你打开一个网站时,浏览器会做许多工作,这其中包括下载各种可能用到的资源,然后渲染呈现在你面前,假设你的网站有大量的图片,那么加载的过程是很耗时的,尤其像那些新闻资讯类需要大量图片的网站,可想而知,网站的初始加载时间会很长,再加上网络等其它影响,用户体验会很差,相信你经常遇到过一个网站卡在某个地方,一直在加载,这种体验很不好。我们都希望一输入网址,页面立马就呈现在眼前。

既然想要页面立马呈现在面前,那势必要减少浏览器的负荷,优化代码,减少一些不必要的请求和不必要资源的加载,因为你打开网站的时候,浏览器会把所有可能的资源都下载好,而实际上有些资源你并不需要用到,这就造成了浪费。所以有必要在一些资源上做下优化,提高网站加载速度。

滚动事件监听

前面说到要等图片出现在视口时才加载,那么肯定要监控浏览器的 scroll 事件,并且要计算图片与浏览器窗口的距离来选择替换图片的 src 地址。代码如下:

HTML
<div>
  <img class="lazy-load" src="https://source.unsplash.com/random/600" alt="">
  <img class="lazy-load" src="https://source.unsplash.com/random/700" alt="">
  <img class="lazy-load" src="https://source.unsplash.com/random/800" alt="">
  <img class="lazy-load" src="https://source.unsplash.com/random/900" alt="">
</div>
// 引入 lodash 库
<script src="https://cdn.bootcss.com/lodash.js/4.17.12-pre/lodash.core.min.js"></script>  

CSS
div {
  margin-top: 350px;
}
.lazy-load {
  width: 200px;
  height: 150px;
}

JS
let lazyImages = [...document.querySelectorAll('.lazy-load')]
let inAdvance = 300
function lazyLoad() {
    lazyImages.forEach(image => {
        if (image.offsetTop < window.innerHeight + window.pageYOffset + inAdvance) {
            image.src = image.dataset.src;   // 替换真实图片的  URL
        }
    })
}
lazyLoad();
window.addEventListener('scroll', _.throttle(lazyLoad, 50))
window.addEventListener('resize', _.throttle(lazyLoad, 50))


这其中有几个属性,首先是 src,它是自定义属性,可以在 js 里通过 dataset 获得它的属性值;还有 offsetTop ,innerHeight 以及 pageYOffset 属性,你可以通过 MDN 文档查询他们的定义和用法;最后是 _.throttle 函数,它是一个节流函数,引用自 lodash 库,因为监听 scroll 滚动以及 resize 窗口改变事件会不断地触发,过于频繁,所以使用节流函数让其每隔一段时间执行,节省开销。

Intersection Observer API

现在,有一个 Intersection observer 接口可以方便我们操作,它可以异步观察目标元素与祖先元素或顶层文件的交集变化。简单的说,以前我们需要自己去写滚动监听事件函数,现在,这个 API 可以帮助我们,我们只需要统一写一个 观察函数 ,每当想观察的元素进入视口,也就是我们看见它时,就执行相应的操作。看看以下 js 代码:

<style>   // css 部分
  .lazy-load {
     width: 400px;
     height: 300px;
   }
</style>
<div>
    <img class="lazy-load" src="https://source.unsplash.com/random/600" alt="">
    <img class="lazy-load" src="https://source.unsplash.com/random/700" alt="">
    <img class="lazy-load" src="https://source.unsplash.com/random/800" alt="">
    <img class="lazy-load" src="https://source.unsplash.com/random/900" alt="">
</div>

document.addEventListener("DOMContentLoaded", function() {
    let lazyImages = [...document.querySelectorAll('.lazy-load')];
    if ("IntersectionObserver" in window) {
        // 创建一个观察函数,以便待会调用   
        let lazyImageObserver = new IntersectionObserver(function(entries, observer) {
            entries.forEach(function(entry) {
            if (entry.isIntersecting) {
               let lazyImage = entry.target;
               lazyImage.src = lazyImage.dataset.src;   // 替换 src URL
               lazyImageObserver.unobserve(lazyImage);  // 解除观察
            }
            });
        });
        // 对所有需要懒加载的图片进行 “暗中观察”
        lazyImages.forEach(function(lazyImage) {
            lazyImageObserver.observe(lazyImage);
        });
     }else{
           alert('您的浏览器不支持 IntersectionObserver');
     }
});

可以看到,里面监听了 DOMContentLoaded 事件,当初始的 HTML 文档被完全加载和解析完成之后,这个事件就被触发,在页面初始之后获取到所有图片元素,然后进行观察。

那既然这个 API 这么好,又简便易用,有没什么缺点呢?相信你看了上面的代码就能知晓,对,浏览器兼容问题!!

2de87deb1798c0a6133cc3f7085cd86d.png

可以看到,还是有很多泛红,只有 Chrome 支持的最好,从 58 以上版本就完全支持了,Firefox 也不错。如果你的项目不需要考虑兼容的话,可以尝试使用下它,看看效果。

Chrome 浏览器自带

这个方法厉害了,没有前面两种方法那么复杂,它是 Chrome 自带的原生 lazyload 属性,只需要一个开关。

chrome://flags/#enable-lazy-image-loading

复制它到 Chrome 浏览器的地址栏,然后找到如下选项,将其设置为「Enabled」。

6a4acc5d19e016ff379b38907f436de6.png

然后在 HTML 标签里开启:

<img src="https://source.unsplash.com/random/600" alt="" lazyload="on">

不需要多余的代码,不需要 JS ,简直强大。

比较三者

秉承着尝试捣鼓新技术的原则,应该优先使用 Intersection Observer ,随着越来越多的浏览器支持会更广泛地应用;但如果要考虑浏览器的兼容问题,那就要使用平常的 scroll,resize 事件监听了,配合 offsetTop 、innerHeight 以及 pageYOffset 几个属性实现。至于最简单粗暴的那个方法,很明显只能在特定的 Chrome 70 以上版本中使用,有很大的局限性,不过现在使用 Chrome 的人非常的多,所以也是有用处的。
综合来看,应该将 Intersection Observerscroll,resize 结合起来使用,这可能是最优也最兼容的方案。

参考资料

[1] MDN 文档:https://developer.mozilla.org/zh-CN/docs/Web/API/Intersection_Observer_API
[2] 延迟加载图像和视频:https://developers.google.com/web/fundamentals/performance/lazy-loading-guidance/images-and-video/
[3] Lazy load images:https://medium.com/@filipvitas/lazy-load-images-with-zero-javascript-2c5bcb691274

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值