IT博客汇
  • 首页
  • 精华
  • 技术
  • 设计
  • 资讯
  • 扯淡
  • 权利声明
  • 登录 注册

    利用IntersectionObserver几行代码简单实现图片懒加载

    1900发表于 2023-06-15 11:55:43
    love 0

    博客之前集成了Douban数据的展示功能,不过由于数据一次性加载过多,且都是有图片的数,导致在进入该网页时会使浏览器卡死3-5秒,等到图片完全加载完毕后才能正常操作,非常影响用户体验。

    我检查了一下,发现卡顿的原因主要还是一次性发起的图片加载请求太多了,查了下资料,似乎下一代的HTTP2.0协议好像对这方面做了优化。但是常规做法还是使用懒加载来处理,也就是滚到图片位置才进行图片请求。

    不过我不太想使用第三方的库来处理这个问题,其他库用起来麻烦,而且很臃肿,我其实只要简单的实现这个功能就好了。之前在移植Smart主题的TOC功能到二〇一九上时发现他使用了 IntersectionObserver 这个函数来处理,便查了一下这个函数的介绍:

    Intersection Observer API 提供了一种异步检测目标元素与祖先元素或 viewport 相交情况变化的方法。

    这个函数多用于以下几种情况

    • 图片懒加载——当图片滚动到可见时才进行加载
    • 内容无限滚动——也就是用户滚动到接近内容底部时直接加载更多,而无需用户操作翻页,给用户一种网页可以无限滚动的错觉
    • 检测广告的曝光情况——为了计算广告收益,需要知道广告元素的曝光情况
    • 在用户看见某个区域时执行任务或播放动画

    后查了一些范例,便参照这个教程的实现了图片的懒加载功能

    <div class="lazyload-wrapper ">
    	<img src="https://iph.href.lu/150x220?text=Loading&fg=666666&bg=cccccc" data-src="{%= o.douban[i].poster %}" referrer-policy="no-referrer" class="lazyload" alt="{%= o.douban[i].title %}" width="150" height="220">
    </div>
    处理图片src
          let images = document.querySelectorAll(".lazyload");
          let observer = new IntersectionObserver(entries => {
            entries.forEach(item => {
              if (item.isIntersecting) {
                item.target.src = item.target.dataset.src; // 开始加载图片,把data-src的值放到src
                observer.unobserve(item.target); // 停止监听已开始加载的图片
              }
            });
          },
            {
              rootMargin: "0px 0px 500px 0px" // 交叉视图前的500像素时,就开始派发事件
            }
          );
          images.forEach(item => observer.observe(item));
    js实现主体
    alt
    rootMargin示例

    原理其实很简单

    • 先修改你的所有图片,将img元素的src属性指定为空或者一个展位图,然后添加的一个data属性存放图片链接,如 data-src ,添加 lazyload 类用于之后可以获取到图片。
    • 通过之前设置的类名获取所有需要懒加载的图片元素。
    • 创建一个IntersectionObserver对象,并传入一个处理函数和rootMagin
    • 处理函数的主要内容是检测被观测到的对象的 isIntersecting(如果 isIntersecting 为真,则该图片至少已经达到我们设置的rootMargin值以内) 判断,如果进入了目标区间内则将img的data-src设置为src属性。
    • 并通过调用 unobserve 停止对这个片检测。

    我记得以前实现起来挺复杂的,现在有了个函数只需要简单的几行代码就可以实现,真的方便。

    END

    🥳
    后续:主题修改完上传到服务器后发现还是会出现卡死的情况,通过使用Chrome的性能工具发现pangu.autoSpacingPage()阻塞了进程...。
    🥳
    后续2:根据「剑公子 」的留言,现代浏览器已经原生支持懒加载,只需要在img标签中添加属性 loading="lazy" 即可。

    通过性能检测工具可以发现 spacingNode 、 spacingNodeByXPath 阻塞了进程,不知道是什么原因。我尝试将调用函数换成 spacingPageBody() 后页面性能恢复正常。可能是body之外的某些标签阻塞了函数执行。

    alt


沪ICP备19023445号-2号
友情链接