介绍图片懒加载的几种实现方法

在 JavaScript 中,懒加载(Lazy Loading)主要用于延迟加载资源,例如图片、视频、音频、脚本等,直到它们真正需要时才加载。这样可以提高页面的加载速度和性能。

以下是几种常见的 JavaScript 懒加载实现方式:

1. 监听滚动事件

通过监听滚动事件来实现图片懒加载是一种传统并且常见的方法,但这种方法在性能上不是很好。

1. 标记页面上哪些图片需要懒加载,使用自定义属性。

<img class="lazy" data-src="real-image.jpg" src="placeholder.jpg" alt="Lazy loaded image">

2.监听滚动事件

window.addEventListener('scroll', lazyLoad);

3. 确定哪些元素已经滚动到了视口内或即将进入视口,需要被加载。 

function lazyLoad() {const lazyImages = [...document.querySelectorAll('.lazy')].filter(isImageInView);  lazyImages.forEach(loadImage);  
}  function isImageInView(img) {  const rect = img.getBoundingClientRect();  return rect.top < window.innerHeight + window.pageYOffset;  
}function loadImage(img) {  img.src = img.dataset.src; // 使用data-src属性中的真实图片地址  img.classList.remove('lazy'); // 移除懒加载类,避免重复加载 
}

4. 注意一点,在页面刚加载时,可能有一些元素已经出在视口内,需要立即加载这些元素,而不仅仅是等待滚动事件。因此在文档加载完成后,立即调用一次 lazyLoad 函数来实现。

document.addEventListener('DOMContentLoaded', function() {  lazyLoad();  
});

由于滚动事件可能非常频繁地触发,因此直接在滚动事件处理函数中执行大量操作可能会导致性能问题。有几种常见的优化方法:函数防抖、函数节流、Intersection Observer API。

我有写过函数防抖和函数节流的文档,忘记的小伙伴可以去看看哦。

2. 交叉观察器

Intersection Observer API 是一种异步观察目标元素与其祖先元素或顶级文档视口的交叉状态的方法。这个 API 提供了一种有效的方式来了解元素何时进入或离开视口(viewport),而无需进行轮询或监听滚动/调整大小事件。这是一个更现代且性能更好的解决方案。

2.1 API 介绍

var io = new IntersectionObserver(callback, option);

IntersectionObserver 是浏览器原生提供的构造函数,接受两个参数:callback 是可见变化时执行的函数,option 时配置对象(可选)。构造函数的返回值是一个观察器实例。实例的 observe 方法可以指定观察哪个 DOM 节点。

// 开始观察
io.observe(document.getElementById('example'));// 停止观察
io.unobserve(element);// 关闭观察器
io.disconnect();

callback 一般会触发两次。一次是目标元素刚进入视口,另一次是完全离开视口。

函数的参数 entries 是一个数组,每个成员都是一个 IntersectionObserverEntry 对象。如果同时有两个被观察对象的可见性发生变化,entries 数组就会有两个成员。

var io = new IntersectionObserver(entries => {console.log(entries);}
);

IntersectionObserverEntry 对象提供目标元素的信息,一共有六个属性。

{time: 可见性发生变化的时间,是一个高精度时间戳,单位为毫秒,rootBounds: 根元素的矩形区域的信息,getBoundingClientRect()方法的返回值,如果没有根元素(即直接相对于视口滚动),则返回 null,boundingClientRect: 目标元素的矩形区域的信息,intersectionRect: 目标元素与视口(或根元素)的交叉区域的信息,intersectionRatio: 目标元素的可见比例,即intersectionRect占boundingClientRect的比例,完全可见时为1,完全不可见时小于等于0,target: 被观察的目标元素,是一个 DOM 节点对象
}

option 是配置对象,有三个属性。

{threshold: 决定何时触发回调函数。它是一个数组,每个成员都是一个门槛值,默认为[0]。root: 指定目标元素所在的容器节点(即根元素)。注意,容器元素必须是目标元素的祖先节点rootMargin: 定义根元素的 margin,用来扩展或缩小 rootBounds 这个矩形的大小,从而影响交叉区域的大小。它使用 CSS 的定义方法,比如10px 20px 30px 40px,表示 top、right、bottom 和 left 四个方向的值。
}

注意:

IntersectionObserver API是异步的,不会阻塞主线程,因此提高了性能。

不随目标元素的滚动同步触发。即只有线程空闲下来,才会执行观察器。意味着这个观察器的优先级非常低,只在其他任务执行完,浏览器有了空闲才会执行。

2.2 实现图片懒加载

1. 标记需要懒加载的图片

<img class="lazy" data-src="real-image.jpg" src="placeholder.jpg" alt="Lazy loaded image">

2. 初始化 IntersectionObserve 

// 回调函数,当元素进入视口时执行  
function handleIntersect(entries, observer) {  entries.forEach(entry => {  if (entry.isIntersecting) {  // 获取图片元素  const lazyImage = entry.target;  // 加载真实图片  lazyImage.src = lazyImage.dataset.src;  // 移除data-src属性,防止重复加载  delete lazyImage.dataset.src;  // 停止观察该元素  observer.unobserve(lazyImage);  }  });  
}  // 创建IntersectionObserver实例  
const options = {  root: null, // 使用视口作为根  rootMargin: '0px', // 根边界与目标元素的边界之间的区域  threshold: 0.1 // 当目标元素的可见比例达到这个阈值时,触发回调函数  
};  
const observer = new IntersectionObserver(handleIntersect, options);

3. 观察懒加载图片 

// 获取所有需要懒加载的图片  
const lazyImages = document.querySelectorAll('.lazy');  // 观察这些图片  
lazyImages.forEach(image => {  observer.observe(image);  
});

4. 处理初始加载

在页面加载时,可能有一些图片已经在视口内。为了确保这些图片也被加载,需要在文档加载完成后立即检查它们的状态。 

document.addEventListener('DOMContentLoaded', (event) => {  // 触发一次检查,确保视口内的图片被加载  lazyImages.forEach(image => {  if (image.getBoundingClientRect().top < window.innerHeight) {  handleIntersect([{ isIntersecting: true, target: image }], observer);  }  });  
});

3. 动态导入

在 JavaScript 中,动态导入(Dynamic Imports)是通过 import() 函数实现的,它允许在运行时按需加载和执行 JavaScript 模块。这种机制特别适用于实现懒加载(lazy loading),因为可以根据需要加载和执行特定的代码块,而不是一次性加载整个应用程序的所有代码。

举个例子 🌰 :

async function loadComponent() {  try {  const { default: MyComponent } = await import('./MyComponent.js');  // 使用 MyComponent // ...  } catch (error) {  // 处理加载错误  console.error('Error loading component:', error);  }  
}  // 在需要的时候调用 loadComponent 函数  
loadComponent();

4. 第三方库

还可以使用许多第三方库来实现懒加载,比如lazysizes、vue-lazyload(Vue.js的懒加载库)等。这些库通常提供了更丰富的功能和更好的性能优化。这里就不多赘述啦。

最后还有一点:

1. 在实现懒加载时,尽量不要破坏页面等语义化结构,比如,不要使用 background-image 代替 <img> 标签。

2. 懒加载不仅限于图片和脚本,还可以应用到其他类型的资源,如 CSS 文件、字体文件等。

3. 对于图片懒加载,最好使用 srcset 和 sizes 属性来提供不同分辨率的图片,以便在不同设备和屏幕尺寸上获得最佳效果。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/18449.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【管理咨询宝藏116】某大型国有集团公司战略落地保障方案

本报告首发于公号“管理咨询宝藏”&#xff0c;如需阅读完整版报告内容&#xff0c;请查阅公号“管理咨询宝藏”。 【管理咨询宝藏116】某大型国有集团公司战略落地保障方案 【格式】PDF版本 【关键词】战略落地、大型国企、战略报告 【核心观点】 - 资产规模以提高资产质量、…

第三部分:领域驱动设计之通过重构得到更深层的理解

通过重构得到更深层的理解 通过重构得到更深层的理解是一个涉及很多方面的过程。有三件事情是必须要关注的: 以领域为本;用一种不同的方式来看待事物;始终坚持与领域专家对话。 开始重构 获得深层理解的重构可能出现在很多方面。一开始有可能是为了解决代码中的问题——一段…

Linux的线程状态

在Linux中,每个进程都有一个当前的状态,这个状态用于标识进程当前正在做什么。你可以通过ps命令配合不同的选项来查看进程的状态。以下是常见的进程状态及其含义: R (running or runnable): 进程正在运行或在运行队列中等待运行。这并不是说进程正在CPU上执行,而是说它处于…

项目十三:搜狗——python爬虫实战案例

根据文章项目十二&#xff1a;简单的python基础爬虫训练-CSDN博客的简单应用&#xff0c;这一次来升级我们的技术&#xff0c;那么继续往下看&#xff0c;希望对技术有好运。 还是老样子&#xff0c;按流程走&#xff0c;一条龙服务&#xff0c;嘿嘿。 第一步&#xff1a;导入…

华为诺亚等发布MagicDrive3D:自动驾驶街景中任意视图渲染的可控3D生成

文章链接&#xff1a;https://arxiv.org/pdf/2405.14475 项目链接&#xff1a;https://flymin.github.io/magicdrive3d 虽然可控生成模型在图像和视频方面取得了显著成功&#xff0c;但在自动驾驶等无限场景中&#xff0c;高质量的3D场景生成模型仍然发展不足&#xff0c;主…

Neo4J中构建的知识图谱,如何使用推理算法

在Neo4j中构建的知识图谱中&#xff0c;推理算法的使用可以极大地增强数据分析和洞察能力。Neo4j提供了多种推理和查询工具&#xff0c;主要通过Cypher查询语言和内置的图算法库来实现。以下是几种常见的推理算法和使用场景&#xff1a; 1. 规则推理&#xff08;Rule-based Re…

2951. 找出峰值 Easy

给你一个下标从 0 开始的数组 mountain 。你的任务是找出数组 mountain 中的所有 峰值。 以数组形式返回给定数组中 峰值 的下标&#xff0c;顺序不限 。 注意&#xff1a; 峰值 是指一个严格大于其相邻元素的元素。 数组的第一个和最后一个元素 不 是峰值。 示例 1&#xf…

关于宏的理解

关于宏的理解&#xff0c; 用宏函数举例 宏会把我们的内容编程一段代码&#xff0c;但是我们宏用的一切都不是变量&#xff0c;就是一个构建代码的符号。 比如下面的例子 char str1[] "1234"; const char* str2 "1234"; char st3[5] { 1,2,3,4,\0 };…

Linux网络编程:应用层协议|HTTP

前言&#xff1a; 我们知道OSI模型上层分为应用层、会话层和表示层&#xff0c;我们接下来要讲的是主流的应用层协议HTTP&#xff0c;为什么需要这个协议呢&#xff0c;因为在应用层由于操作系统的不同、开发人员使用的语言类型不同&#xff0c;当我们在传输结构化数据时&…

【全开源】宇鹿家政系统(FastAdmin+ThinkPHP+原生微信小程序)

&#xff1a;助力家政行业数字化升级 一、引言&#xff1a;家政服务的新篇章 随着移动互联网的普及和人们生活水平的提高&#xff0c;家政服务的需求日益增长。为了满足这一市场需求&#xff0c;并推动家政行业的数字化升级&#xff0c;我们特别推出了家政小程序系统源码。这…

excel 点击单元格的内容 跳转到其他sheet设置

如图点击1处跳转到2 按照如下图步骤操作即可

oracle 分区表常用语句(2)

给分区表增加分区 第一种不存在MAXVALUE(直接添加即可&#xff09; ALTER TABLE T6 ADD PARTITION P5 VALUES LESS THAN(TO_DATE( 2018-08-01 00:00:00, SYYYY-MM-DD HH24:MI:SS, NLS_CALENDARGREGORIAN));第二种存在MAXVALUE alter table T6 split PARTITION P4 at(TO_DAT…

电机控制系列模块解析(25)—— 过压抑制与欠压抑制

一、概念解析 变频器作为一种重要的电机驱动装置&#xff0c;其内置的保护功能对于确保系统安全、稳定运行至关重要。以下是关于变频器过压抑制、欠压抑制&#xff08;晃电抑制&#xff09;、发电功率限制、电动功率限制等保护功能的详细说明&#xff1a; 过压抑制 过压抑制是…

Android Audio基础——缓冲区大小获取(十三)

前面使用 AudioTrack 播放音频数据,在创建 AudioTrack 时其中有一个是缓冲区大小的参数,通过 AudioTrack.getMinBufferSize() 获取最小缓冲区。这一节我们就来分析下缓冲区大小参数的作用。 一、最小缓冲区 最小缓冲区是声音能正常播放的最低保障。如果数据缓冲区分配得过小…

C语言期末习题之二维数组转置

1.题目 写一个函数&#xff0c;使得给定的44的二维数组x[4][4]转置&#xff0c;即进行列互换。 2.思路 这个题可以使用两层循环来遍历给定的二维数组&#xff0c;然后将每一列的元素与对应行的元素进行交换&#xff0c;从而实现转置操作。具体思路如下&#xff1a; 1. 使用两层…

c++【入门】你多大了

时间限制 : 1 秒 内存限制 : 128 MB 一天玩仔跑来问周周你多大了&#xff0c;周周告诉他自己 1010 岁了&#xff0c;玩仔又说自己也是&#xff0c;你听到了这个对话&#xff0c;想用程序显示出两个人的对话内容&#xff0c;现在就来试一试吧。 输入 无 输出 输出三行&…

今日早报 每日精选15条新闻简报 每天一分钟 知晓天下事 5月29日,星期三

每天一分钟&#xff0c;知晓天下事&#xff01; 2024年5月29日 星期三 农历四月廿二 1、 首个未成年人游戏退费标准发布&#xff1a;监护人与网游服务提供者将按错担责。 2、 六部门联合印发通知&#xff1a;鼓励加快高清超高清电视机等普及、更新。 3、 神舟十八号航天员乘…

【图像识别的革命:卷积神经网络(CNN)的原理与应用】

文章目录 前言卷积神经网络的基础构建一个简单的CNN模型分析代码结论 前言 在深度学习的众多成就中&#xff0c;卷积神经网络&#xff08;CNN&#xff09;在图像识别领域的突破尤为显著。CNN通过其独特的结构和算法&#xff0c;能够自动从图像中提取特征&#xff0c;极大地提高…

AI播客下载:Acquired podcast每个公司都有一个故事

"Acquired Podcast" 是一档专注于深度解析科技行业和企业发展历程的播客节目&#xff0c;由Ben Gilbert和David Rosenthal主持。其口号是&#xff1a;Every company has a story.《Acquired》每一集都围绕一个特定的主题或公司进行讨论。它以独特的视角和深入的分析&…

vue组件通讯vuex状态管理例子

Vuex 是 Vue.js 的状态管理模式和库。它采用集中式存储管理应用的所有组件的状态&#xff0c;并以相应的规则保证状态以一种可预测的方式发生变化。以下是一个简单的 Vuex 状态管理例子&#xff0c;展示如何在 Vue 组件中使用 Vuex 进行通讯。 首先&#xff0c;我们需要安装并…