首页 > 其他分享 >介绍图片懒加载的几种实现方法

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

时间:2024-05-28 17:30:16浏览次数:12  
标签:滚动 函数 元素 几种 视口 加载 图片

在 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),因为可以根据需要加载和执行特定的代码块,而不是一次性加载整个应用程序的所有代码。

举个例子

标签:滚动,函数,元素,几种,视口,加载,图片
From: https://blog.csdn.net/weixin_52648900/article/details/139267200

相关文章

  • Nginx(openresty) 通过lua结合Web前端 实现图片,文件,视频等静态资源 访问权限验证,进行
    1本文系统环境:安装openresty(nginx),可参考:test@ubuntuserver:~$cat/etc/os-releasePRETTY_NAME="Ubuntu24.04LTS"NAME="Ubuntu"VERSION_ID="24.04"VERSION="24.04LTS(NobleNumbat)"VERSION_CODENAME=nobleID=ubuntuID_LIK......
  • Dolphinscheduler不重启加载Oracle驱动
    转载自刘茫茫看山问题背景某天我们的租户反馈数据库连接缺少必要的驱动,我们通过日志查看确实是缺少部分数据库的驱动,因为DolphinScheduler默认只带了Oracle和MySQL的驱动,并且需要将pom文件中的test模式去掉才可以在打包的时候引入。我们的任务量比较大,在3.0存在容错机制的情况下......
  • md路径正确但是图片不显示的原因
    从flowus导出文章后,发现虽然路径是正确的,但是在预览中无法显示图片。后来发现是路径中带有空格的原因,解决方法是使用%20替代路径中的空格另外还有一个坑点是:如果你的vscode的formatter是prettier,并且对于md没有做忽略设置,那么在保存的时候可能也会破坏你的文件路径链接,导致无......
  • .net core的WebAPI+Vue2实现调用设备拍照上传图片功能
    在工作中有时候会遇到上传文件上传图片或者拍照上传图片功能。这时候底下的内容就有可能可以帮助到你。后端的支持上传图片和上传文件功能。前端如果你选择普通上传功能就是普通上传功能,我这里选择的是调用相机设备实现拍照上传图片功能。1.首先这是后端的控制器接口。1///<......
  • 2024最新ChatGPT网站源码+AI绘画系统源码,详细图文搭建教程/支持ChatGPT4.0/GPT-4o文档
    一、文章前言SparkAi创作系统是基于ChatGPT进行开发的Ai智能问答系统和Midjourney绘画系统,支持OpenAI-GPT全模型+国内AI全模型。本期针对源码系统整测试下来非常完美,那么如何搭建部署AI创作系统呢?小编这里写一个详细图文教程吧。支持GPT-4o大模型、GPTs应用、GPT语音对话、联......
  • 异步数据加载与绑定设计: AsyncLoadHelper
    在现代应用程序开发中,异步数据加载和管理是一个普遍的需求。本文介绍了一个自定义的异步数据加载工具——AsyncLoadHelper。通过详细的设计和实现介绍,以及结合实际应用示例,展示了AsyncLoadHelper在简化异步操作、提高代码可读性和维护性方面的优势。在开发过程中,异步数据加载常常......
  • vue首屏加载动画打包后失效
    本地环境运行时,没有问题,打包后,加载动画没有效果,尝试修改:extract:false后成功。 加载动画示例:index.html中<linkrel="stylesheet"href="static/css/loading.css"/><body><divid="app"><divid="appLoading"><d......
  • 【一步步开发AI运动小程序】十八、如何识别用户上传图片中的人体、运动、动作、姿态?
    【云智AI运动识别小程序插件】,可以为您的小程序,赋于人体检测识别、运动检测识别、姿态识别检测AI能力。本地原生识别引擎,内置10余个运动,无需依赖任何后台或第三方服务,有着识别速度快、体验佳、扩展性强、集成快、成本低的特点,本篇实现需要使用此插件,请先行在微信服务市场或官网了......
  • WPF Splash Screen – A New Splash Screen Manager (v20.1) 启动页 闪屏页 初始加载
    WPFSplashScreen–ANewSplashScreenManager(v20.1)(devexpress.com)  WPFTeamBlog RSS06July2020A splashscreen isaneffectivewaytoimproveanapp’suserexperienceduringlengthystartupoperations.Unfortunately,creatinganef......
  • WPF开发01-数据绑定的几种方式,静态,动态、向上查找、适应各种情况
    1.前后端简单绑定第一种比较常见,常见于mvvm框架前端<TextBlockText="{BindingPath=Name}"></TextBlock>1后端publicclassPersonViewModel:INotifyPropertyChanged{publicstringName{get{returnname;}set{if(name......