面试官:前端实现图片懒加载怎么做?这不是撞我怀里了嘛!
前端懒加载(也称为延迟加载或按需加载)是一种网页性能优化的技术,主要用于在网页中延迟加载某些资源,如图片、视频或其他媒体文件,直到它们实际需要被用户查看或交互时才进行加载。这种技术特别适用于长页面或包含大量媒体资源的页面,因为它可以显著提高页面加载速度,减少用户等待时间,并降低服务器负载。
懒加载的原理为基于视口(viewport)的概念,即用户当前在屏幕上可见的区域。当页面加载时,只有视口内的资源会被立即加载,而视口外的资源则会被延迟加载。当用户滚动页面或触发其他交互行为时,视口外的资源才会根据需要被加载。
懒加载的优点:
- 提高页面加载速度:由于只加载视口内的资源,页面初始加载时间大大减少。
- 节省带宽和服务器资源:减少不必要的资源加载,降低服务器负载和带宽消耗。
- 提升用户体验:减少用户等待时间,使页面更加流畅和响应迅速。
那么实现懒加载的方式有哪些呢?本文主要从原生、vue、react角度来说一下实现懒加载的常见方法!
一、原生的loading属性
loading 属性指定浏览器是应立即加载图像还是延迟加载图像。现代浏览器已经开始支持img标签的loading属性。设置 loading=“lazy” 只有鼠标滚动到该图片所在位置才会显示。
loading的属性值有eager和lazy,默认值为eager,表示图像立即加载;lazy表示图像延迟加载,只有鼠标滚动到该图片所在位置才会显示。
<img src="/images/paris.jpeg" alt="Paris" loading="lazy">
<img src="/images/nature.jpeg" alt="Nature" loading="lazy">
这是实现懒加载最简单的方法,无需额外的JavaScript代码。
二、Intersection Observer API
Intersection Observer API(交叉观察器 API)提供了一种异步检测目标元素与祖先元素或顶级文档的视口相交情况变化的方法。
过去,要检测一个元素是否可见或者两个元素是否相交并不容易,很多解决办法不可靠或性能很差。然而,随着互联网的发展,这种需求却与日俱增,比如,在页面滚动时“懒加载”图像或其他内容这些情况都需要用到相交检测。
const io = new IntersectionObserver(callback, option);
IntersectionObserver是浏览器原生提供的构造函数,接受两个参数:callback是可见性变化时的回调函数,option是配置对象(该参数可选)。
构造函数的返回值是一个观察器实例。实例的observe方法可以指定观察哪个 DOM 节点。
// 开始观察
io.observe(document.getElementById('example'));// 停止观察
io.unobserve(element);// 关闭观察器
io.disconnect();
上面代码中,observe的参数是一个 DOM 节点对象。如果要观察多个节点,就要多次调用这个方法。
io.observe(elementA);
io.observe(elementB);
**callack参数:**目标元素的可见性变化时,就会调用观察器的回调函数callback。
一般会触发两次:(1)目标元素刚刚进入视口(开始可见);(2)完全离开视口(开始不可见)。
callback函数的参数是一个数组,每个成员都是一个IntersectionObserverEntry对象。
**IntersectionObserverEntry 对象:**提供目标元素的信息,一共有六个属性。
- time:可见性发生变化的时间,是一个高精度时间戳,单位为毫秒。
- target:被观察的目标元素,是一个 DOM 节点对象。
- rootBounds:根元素的矩形区域的信息,getBoundingClientRect()方法的返回值,如果没有根元素(即直接相对于视口滚动),则返回null。
- boundingClientRect:目标元素的矩形区域的信息。
- isIntersecting: 布尔值,目标元素与交集观察者的根节点是否相交(常用)。
- intersectionRect:目标元素与视口(或根元素)的交叉区域的信息。
- intersectionRatio:目标元素的可见比例,即intersectionRect占boundingClientRect的比例,完全可见时为1,完全不可见时小于等于0。
所以可以通过判断isIntersecting属性是否为true来判断元素的可见性。
对于需要懒加载的图片,使用data-src代替src。
<img data-src="image.jpg" alt="description">
document.addEventListener("DOMContentLoaded", function() {const images = document.querySelectorAll('img[data-src]');const loadImage = function(image) {image.setAttribute('src', image.getAttribute('data-src'));image.onload = function() {image.removeAttribute('data-src');}}//使用IntersectionObserver监听元素是否进入可视区域if ('IntersectionObserver' in window) {var observer = new IntersectionObserver(function(items, observer) {items.forEach(function(item) {if (item.isIntersecting) {loadImage(item.target);observer.unobserve(item.target);}});}, {threshold: 0.01});images.forEach(function(img) {observer.observe(img);});} else {//不支持IntersectionObserver,直接加载所有图片images.forEach(function(img) {loadImage(img);});}
});
四、事件监听+getBoundingClientReact()
旧版本的浏览器可能不支持Intersection ObserverAPI,此时可以用 getBoundingClientRect 和事件监听结合来实现。
Element.getBoundingClientRect() 方法返回一个 DOMRect 对象,其提供了元素的大小及其相对于视口的位置。
返回值是一个 DOMRect 对象,是包含整个元素的最小矩形(包括 padding 和 border-width)。该对象使用 left、top、right、bottom、x、y、width 和 height 这几个以像素为单位的只读属性描述整个矩形的位置和大小。除了 width 和 height 以外的属性是相对于视图窗口的左上角来计算的。
const rectObject = object.getBoundingClientRect()
因此,当rectObject.top的值处于0-视口高度,则元素处于可视区。即
getBoundingClientRect(ele).top >= 0 && getBoundingClientRect(ele).top <= offsetHeight
实现如下:
function isElementInviewport(el) {const rect = el.getBoundingClientRect();return (rect.bottom >= 0 &&rect.right >= 0 &&rect.top <= (window.innerHeight || document.documentElement.clientHeight) && rect.left <= (window.innerwidth || document.documentElement.clientWidth);)
}function checkLazyLoad() {const lazyImages = Array.prototype.slice.call(document.querySelectorAll('img[data-src]'));lazyImages.forEach(function(img) {if (isElementInViewport(img)) {img.src = img.getAttribute('data-src');img.removeAttribute('data-src');}});if (lazyImages.length === 0) { //如果所有懒加载图片都已加载,移除滚动监听window.removeEventListener('scroll', checkLazyLoad);window.removeEventListener('resize', checkLazyLoad);}
}//监听事件
window.addEventListener('scroll', checkLazyLoad);
window.addEventListener('resize', checkLazyLoad);
window.addEventListener('DOMContentLoaded', checkLazyLoad);
五、使用第三方库
许多第三方库可以实现懒加载,例如lazysizes 和lozad.js。
以下是使用 lazysizes 库的示例:
首先,你需要引入lazysizes 库。
<script src="lazysizes.min.js" async=""></script>
然后修改你的标签,增加lazyload 类和data-src 属性来取代 src即可。
<img data-src="image.jpg" class="lazyload" alt="image" />
Iazysizes 库会自动处理剩下的工作。
六、vue中使用vue-lazyload
在Vue中vue-lazyload插件用的比较多。
首先,安装vue-lazyload:
npm install vue-lazyload--save
接着在你的Vue项目中引入并使用vue-lazyload:
// main.js
import Vue from 'vue'
import App from './App.vue'
import VueLazyload from 'vue-lazyload'
Vue.use(VueLazyload)
//或者添加选项,例如加载时的占位图或加载失败时的图像
Vue.use(VueLazyload, {preLoad: 1.3,error: 'error.png',loading: 'loading.gif',attempt: 1
})
new Vue({render: h => h(App)
}).$mount('#app')
然后在组件中使用v-lazy指令来替换src属性:
<img v-lazy="imgUrl" alt="image">
七、React中的lazy函数
React项目中,你可以使用React自带的lazy函数结合Suspense组件来实现图片懒加载。
React.lazy目前仅支持默认导出(default exports)如果要加载的组件使用了命名导出,你需要一个中间模块来重新导出它为默认模块。
首先,你需要创建一个懒加载组件来包装图片:
// LazyImage.jsx
import React from'react';
const LazyImage = ({ src, alt }) => {return(<img src={src} alt={alt} />);
};
export default LazyImage;
然后使用React.lazy来动态导入这个组件:
// App.js 或者其他父组件
import React, { Suspense } from 'react';
const LazyImage = React.lazy(() => import('./LazyImage'));
// 懒加载组件
const App = () =>{return (<div><Suspense fallback={<div>Loading...</div>}>{/* 在Suspense组件中渲染懒加载的组件 */}<LazyImage src="image.jpg" alt="图片描述"/></Suspense></div>);
};
export default App;
Suspense 组件允许你在等待加载时显示一个加载指示器(例如上面的
总结
注意事项
- 兼容性:不同的浏览器和设备对懒加载的支持程度不同,需要确保所选用的懒加载方案具有良好的兼容性。
- 用户体验:懒加载不应该影响用户的正常浏览和操作。例如,在图片加载过程中,可以显示占位符或加载提示,以增加用户的等待体验。
- SEO优化:虽然懒加载可能会对SEO造成一定影响,但可以通过合理的策略来优化。例如,确保关键内容和链接在初始加载时即可被搜索引擎索引。
应用场景
- 长页面和图片密集型网站:如新闻网站、社交媒体、电商网站等,这些网站通常包含大量的图片和长页面,采用懒加载可以显著提高页面性能和用户体验。
- 视频和音频资源丰富的网站:如视频分享网站、音乐平台等,这些网站的视频和音频资源占用大量带宽和服务器资源,采用懒加载可以有效降低服务器负载和带宽消耗。
- 移动设备优化:移动设备的网络环境通常较差,采用懒加载可以减少用户的流量消耗和等待时间,提升用户体验。
总之,懒加载技术广泛应用于各类网站和应用中,特别是长页面、图片密集的网站、电商网站、新闻网站等。在这些场景中,懒加载技术可以显著提高页面性能和用户体验。
相关文章:
面试官:前端实现图片懒加载怎么做?这不是撞我怀里了嘛!
前端懒加载(也称为延迟加载或按需加载)是一种网页性能优化的技术,主要用于在网页中延迟加载某些资源,如图片、视频或其他媒体文件,直到它们实际需要被用户查看或交互时才进行加载。这种技术特别适用于长页面或包含大量…...
每天学习一个Windows命令或Linux命令——seq
今天我们来学习 seq命令! seq命令(单词sequence序列的缩写)是Linux系统中用于输出序列化的一串整数的命令。 一、seq用法 seq用法一共有以下三种: seq [选项]... 尾数 seq [选项]... 首数 尾数 seq [选项]... 首数 增量&#…...
C++设计模式-中介者模式,游戏对象之间的碰撞检测
运行在VS2022,x86,Debug下。 31. 中介者模式 中介者模式允许对象之间通过一个中介者对象进行交互,而不是直接相互引用。可以减少对象之间的直接耦合,同时集中化管理复杂的交互。应用:如在游戏开发中,可以使…...
Rust-02-变量与可变性
在Rust中,变量和可变性是两个重要的概念。 变量:变量是用于存储数据的标识符。在Rust中,变量需要声明其类型,例如: let x: i32 5; // 声明一个名为x的变量,类型为i32(整数)&#…...
mov指令中不允许的操作——汇编语言
在 x86 汇编语言中,MOV 指令的限制有助于确保系统的稳定性和正确的操作。下面详细解释为什么这些操作是不允许的。 1. 段寄存器之间直接传送数据 MOV DS, ES ; 错误,不允许原因: 段寄存器是用来定义程序段的开始位置,如代码段…...
Python进阶-部署Flask项目(以TensorFlow图像识别项目WSGI方式启动为例)
本文详细介绍了如何通过WSGI方式部署一个基于TensorFlow图像识别的Flask项目。首先简要介绍了Flask框架的基本概念及其特点,其次详细阐述了Flask项目的部署流程,涵盖了服务器环境配置、Flask应用的创建与测试、WSGI服务器的安装与配置等内容。本文旨在帮…...
WooYun-2016-199433 -phpmyadmin-反序列化RCE-getshell
参考资料: Phpmyadmin 脚本/设置.php反序列化漏洞 (WooYun-2016-199433)复现_phpmyadmin scriptssetup.php 反序列化漏洞-CSDN博客 https://blog.csdn.net/haoxue__/article/details/129368455利用pearcmd.php文件包含拿shell(L…...
社交“学习伙伴”:Meta Llama助力对话升级
每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗?订阅我们的简报,深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同,从行业内部的深度分析和实用指南中受益。不要错过这个机会,成为AI领…...
LabVIEW 反向工程的实现与法律地位
什么是LabVIEW反向工程? 反向工程是指从现有的应用程序或软件中推导出其设计、架构、代码等信息的过程。对于LabVIEW而言,反向工程涉及从现有的VI(虚拟仪器)文件、项目或应用程序中提取出设计思路、功能模块、算法实现等。 LabV…...
Python怎么做单元测试
在Python中,最常用的单元测试框架是unittest。以下是如何使用unittest进行单元测试的步骤: 导入unittest模块: 首先,你需要导入unittest模块。 import unittest创建测试类: 你需要创建一个继承自unittest.TestCase的类…...
ghidra
https://github.com/NationalSecurityAgency/ghidra ghidra是一个so的逆向工具,功能和jadx-gui类似,但是和jadx-gui专注于java层的不同,ghidra专注于native层的代码反编译(从二进制到c语言)。 一、 安装 准备好java1…...
如何解决网络问题?
组织和 IT 管理员尽其所能完善他们的网络,但是,不同程度的网络问题仍然可能出现,这些网络问题需要立即响应和解决,如果这些问题在不合理的时间内得不到解决,网络和组织的损害可能会付出高昂的代价。这就是为什么 IT 管…...
高速USB转串口芯片CH343
CH343封装 截止目前,主要封装有 SOP16: CH343G QFN16: CH343P ESSOP10: CH343K,截止24年6月未生产 CH343串口速度 最高串口速度: 6Mbps,比CH340的2M,快3倍 1、概述 参考版本:1E CH343 是一个 USB 总线的转接芯片,…...
C++ MPI多进程并发
下载 用法 mpiexec -n 8 $PROCESS_COUNT x64\Debug\$TARGET.exe 多进程并发启动 mpiexec -f hosts.txt -n 3 $PROCESS_COUNT x64\Debug\$TARGET.exe 联机并发进程,其它联机电脑需在相同路径下有所有程序 //hosts.txt 192.168.86.16 192.168.86.123 192.168…...
UFS协议入门-分层结构
写在前面:本文参考UFS jedec3.1,本文思维导图如下 1. 分层概述 UFS协议分为3层,从上至下分别是:应用层(UAP),传输层(UTP),互联层(UIC),具体结构如下图所示。 2.1 应用层 在应用层(UAP)中,包括:UFS指令集(UCS),设备管理器(Device Manager),任务管理器(Task Manager…...
Docker Desktop - WSL distro terminated abruptly
打开 PowerShell 或以管理员身份运行的命令提示符。运行以下命令以列出已安装的 WSL 分发: wsl --list 运行以下命令以注销 Docker 相关的分发 wsl --unregister <distro_name> 将<distro_name>替换为实际的 Docker 相关分发的名称。将<distro_…...
HTML-CSS练习例子
HTML CSS 练习 https://icodethis.com 作为前端练习生。不敲代码只看,入门是很慢的,所以直接实战是学习前端最快的途径之一。 这个网站练习HTML CSS的,可以打开了解一下,可以每天打卡,例子简单,循序渐进&…...
【JavaScript脚本宇宙】创造声音的魔法:深入了解Web音频处理库
聆听创意可能性:解锁Web音频库的神奇功能 前言 在Web开发中,处理音频是一个重要且常见的需求。许多JavaScript库和框架旨在简化音频处理和交互式音乐的创建过程。本文将探讨几个流行的Web音频库,介绍它们的概述、主要特性、使用示例以及适用…...
苹果需要专注于让人工智能变得实用,而不是华而不实
谷歌和微软已将其开发者大会作为展示其生成式人工智能能力的平台,现在所有人的目光都集中在下周的全球开发者大会上,预计Apple Intelligence将在此首次亮相。 这家总部位于库比蒂诺的公司面临着巨大的压力。 苹果在人工智能竞赛中落后于同行࿰…...
安全专业的硬件远控方案 设备无网也能远程运维
在很多行业中,企业的运维工作不仅仅局限在可以联网的IT设备,不能连接外网的特种设备也需要专业的远程运维手段。 这种特种设备在能源、医疗等行业尤其常见,那么我们究竟如何通过远程控制,对这些无网设备实施远程运维,…...
Freeswitch-soundtouch-变声开发
文章目录 一、介绍二、安装soundtouch2.1 源码安装方式(推荐)2.1.1下载源码2.1.2解压2.1.3 编译2.1.4 迁移(可选) 2.2 apt-get 安装 三、使用3.1 终端使用3.2 Freeswitch使用3.2.1编译Freeswitch的mod_soundtouch3.2.2启用 mod_so…...
Unity2D游戏制作入门 | 09(之人物动画制作)
上期链接:Unity2D游戏制作入门 | 08-CSDN博客 人物走路动画逻辑补充(该帖没有的内容,我给补充了请先看完这帖,再去看补充):人物按下shifit走路动画设定09(第九期先行补充) 上期我们…...
【自动部署】4.阿里云ECS服务器 IDEA自动部署项目
如何在IDEA中,自动部署项目到阿里云ECS服务器?今天我们就来实现一键部署功能。 执行maven命令打包免密登录,在IEDA中连接服务器执行stop脚本上传jar包到服务器执行start脚本查看运行日志 1.安装Alibaba Cloud Toolkit 2.配置host 3.自动化部…...
[Algorithm][动态规划][01背包问题][目标和][最后一块石头的重量Ⅱ]详细讲解
目录 1.目标和1.题目链接2.算法原理详解3.代码实现 2.最后一块石头的重量 II1.题目链接2.算法原理详解3.代码实现 1.目标和 1.题目链接 目标和 2.算法原理详解 问题转化:在数组中选择一些数,让这些数的和等于a,一共有多少种选法?…...
LabVIEW控制PLC的实现方式
LabVIEW与PLC的结合可以充分发挥两者的优点,实现更高效、灵活和可靠的自动化控制系统。本文将详细介绍LabVIEW控制PLC的实现方式,包括通信接口、数据交换、编程方法及实际应用案例,帮助用户理解并应用这一技术。 通信接口 常见通信协议 La…...
JSTL知识点讲解与配置
JSTL(JavaServer Pages Standard Tag Library)是Java EE平台中的一个标准库,提供了一组用于在JSP(JavaServer Pages)中简化和标准化常见任务的标签。这些标签封装了很多常见的JSP功能,可以使得JSP页面更加简…...
Autodesk 3ds Max软件下载安装;3ds Max功能强大的三维建模、渲染软件安装包获取
3ds Max,无论是初学者还是资深设计师,都能通过3ds Max在数字世界中实现自己的创意,打造出令人惊叹的三维作品。 在3ds Max中,灯光系统是至关重要的一环。它提供了光度学灯光和标准灯光两种主要类型,用于照亮和增强场景…...
联合体和枚举<C语言>
导言 在C语言中除了结构体外,联合体和枚举也是自定义类型,联合体主要用于节省空间,在同一块内存存储多种类型的数据,而枚举可以提高代码的可读性、可维护性。 联合体(union) 它还有个更容易理解的名字&…...
算法人生(21):从“React框架”看“情绪管理”
说起React框架,我们知道它是一种由Facebook开发和维护的开源JavaScript库,主要用于构建用户界面,特别是单页应用程序(SPA)。React框架围绕组件化,即把用户界面拆分为可复用的独立组件,每个组件负…...
千益畅行:合法合规的旅游卡服务,真实可靠的旅游体验
近期,关于千益畅行旅游卡服务的讨论引起了广泛关注。然而,网络上出现了一些对其误解和质疑的声音。为了澄清事实,我们深入了解了千益畅行的运营模式和业务特点,发现它是一家合法合规的旅游卡服务提供商,为消费者提供真…...
拓者设计吧现代装修效果图/优化大师的作用
Token Contrast for Weakly-Supervised Semantic Segmentation 摘要 目的: 使用图像级标签的弱监督语义分割(WSSS)通常利用类激活映射(CAM)生成伪标签。受CNN局部结构感知的限制,CAM通常不能识别整体目标区域。虽然最近的视觉转换器(ViT)可以弥补这一…...
南宁网站建设怎么样/跨境电商平台排行榜前十名
/* reference http://nehe.gamedev.net/article/using_gluunproject/16013/ */#include <windows.h> // windows系统要加这个。因为下面2个头文件的一些宏是在这个文件中定义的 #include <gl/Gl.h> #include <gl/glut.h> //这两个头文件在OpenGL程序中…...
具有口碑的柳州网站建设哪家好/seo优化搜索推广
P4231 三步必杀 差分数组差分数组一看等差数列思路就往奇怪的地方去了……突然想到常数列前缀和就是等差又想到上周D1T1后缀和的后缀和就是类似的东西所以在题目明显暗示差分的情况下做一下差分的差分然后由于最后求前缀和只需要1~n所以就只需要每次在差分数组上修改…...
手游app平台推广微信xiala5/昆明seo工资
自已开发的一个日历项目,其中一个显示日程列表的Activity只有一个ListView,数据来源于数据库。 在这个xxxActivity.java里面添加了: /** Create menu. */ public booleanonCreateOptionsMenu(Menu menu) { MenuInflater mMenuInflater getMe…...
做网络歌手的网站/百度一下你就知道123
比explain更加详细的分析计划:Query Profiler 2019-05-10 14:47:45 阅读:78 来源: 互联网 标签:profile show explain sql profiles Profiler query Query 一、前言 这篇博客是之前总结的一个知识点,也是偶然看别人…...
如何用自己电脑做网站/长春seo招聘
目录13.1、枚举类13.1.1、概述13.1.2、自定义枚举类13.1.2.1、第一版13.1.2.2、第二版13.1.2.3、第三版13.1.2.4、测试方法13.1.3、系统的枚举类13.1.3.1、第一版13.1.3.2、第二版13.1.3.3、第三版13.1.3.4、测试方法13.1.4、常见方法13.1.5、注意事项13.2、注解13.2.1、概述13…...