使用IntersectionObserver实现图片懒加载功能

前言

上一期我们聊了如何实现图片懒加载功能,其思路是src地址使用一张内存很小的占位图,真实的图片我们放在data-src中,当图片滚动到视窗时,将data-src的值赋给src,并且给滚动事件添加节流函数实现懒加载。这期我们使用更加高级的语法,用intersectionObserver实现图片懒加载功能。它不仅可用于图片懒加载场景下,还能用于无限滚动列表下,让我们一起看看这是怎么实现的吧。

IntersectionObserver

首先我们介绍一下IntersectionObserver如何使用。

IntersectionObserver 是一种浏览器API,用于异步监测一个元素相对于另一个元素或视口的可见性变化。

基本概念

目标元素

  • 被监测的元素,即你想知道何时进入或离开视口或某个容器的元素。

根元素

  • 相对于其可见性的元素。如果没有指定,则默认为视口(浏览器窗口)。

阈值(Threshold)

  • 一个或多个表示触发回调的阈值。当目标元素可见部分占目标元素总大小的比例达到这些阈值时,回调函数会被调用。阈值可以是单个值或数组。

回调函数

  • 当目标元素的可见性发生变化时执行的函数。这个函数会接收到一个包含所有可见性变化记录的数组。

基本使用

创建 IntersectionObserver 实例

通过传递回调函数和可选的配置对象来创建一个新的 IntersectionObserver 实例。

ini 复制代码
const observer = new IntersectionObserver(callback, options);

回调函数

当目标元素的可见性发生变化时,会调用这个函数。

ini 复制代码
const callback = (entries, observer) => {
  entries.forEach(entry => {
    if (entry.isIntersecting) {
      // 目标元素进入视口
    } else {
      // 目标元素离开视口
    }
  });
};

配置选项

包含 rootrootMarginthreshold 的对象。

csharp 复制代码
const options = {
  root: null, // 默认为视口
  rootMargin: '0px',
  threshold: 0.5 // 当目标元素50%可见时触发回调
};

观察目标元素

调用 observe 方法开始观察目标元素。

ini 复制代码
const target = document.querySelector('.target-element');
observer.observe(target);

停止观察

可以随时调用 unobserve 方法停止观察某个元素,或者调用 disconnect 方法停止观察所有元素。

ini 复制代码
observer.unobserve(target);
observer.disconnect();

图片懒加载应用

思路:我们同样还是用占位图的方式实现,创建IntersectionObserver实例对象observer,调用observe方法观测所有图片的dom节点,在IntersectionObserver实例对象的回调函数里实现当观测到图片进入视口时,我们就将占位图换成真实的图片地址,并且停止观察这个元素。

代码实现

javascript 复制代码
document.addEventListener('DOMContentLoaded', function () {
			//获取所有的图片节点
            const images = document.querySelectorAll('.lazy');
            //将占位图换成真实图片
            const loadImg = (image) => {
                image.src = image.dataset.src;
                image.classList.remove('lazy');
            }
            // 创建观察对象 entries => 观察到的元素列表
            const observer = new IntersectionObserver((entries) => {
                entries.forEach((entry) => {
                    // 判断是否进入可视区域
                    if (entry.isIntersecting) {
                        // 加载图片
                        loadImg(entry.target);
                        // 停止观察
                        observer.unobserve(entry.target);
                    }
                })
            },{
                rootMargin:'0px', //没有扩展或收缩根的边界,即使用视口的实际边界。
                threshold:0.5 //用于指定目标元素的可见部分与根的交集比例
            })
            images.forEach(image => {
                observer.observe(image);
            });
        })
相关推荐
子兮曰1 天前
jev-ultrafast 深度解析:7 秒订机票的浏览器 Agent 是如何炼成的
前端·后端·agent
子兮曰1 天前
Jev 爆发一周:7 秒 Agent 背后的 System One 生态与三场争议
前端·后端·ai编程
前端小万1 天前
写公众号赚了 3000 块后,我做了一款叫 "一键成稿" 的软件
前端·微信小程序
爱勇宝1 天前
ZCode 开源 24 小时:一份没有历史的账本,回答不了"有没有偷代码"
前端·后端·chatglm (智谱)
三十而立洋1 天前
Cookie 详解:从产生到安全,一次讲透
前端·javascript
卡布鲁2 天前
把一个 Vite + Vue3 应用塞进 qiankun (React + Umi3) 主站:十个坑的复盘
前端·javascript·react.js
李少兄2 天前
JavaScript 隐式全局变量解析
javascript
汉堡大王95272 天前
Jev:不是聊天机器人, 而是一个智能 if 语句
前端·人工智能·后端
梦想很大很大2 天前
从运行事实到回归证据:Workrun 的 Telemetry 与 Evaluation 实践
前端·人工智能·后端
计算机魔术师2 天前
Meta Muse agent 接入 Shopify 的 Shop Pay 实现代理式购物
前端