谈谈面试常考题:懒加载,防抖,节流(方法实现详解)

前言

最近在学习中确实收获了挺多东西,其中我觉得有必要拿来进行分享一下的就是懒加载了,还有相关的防抖和节流。因为在浏览器中这些都是属于很常见的性能优化,面试也是常考题。话不多说,速度发车。

什么是懒加载?懒加载实现了什么效果?

image.png

引言

像上图中的百度图片,有成千上万的图片,但是每个图片都是通过网络请求进行拿到。虽然是异步进行但是同时进行大量图片的请求,整个页面的渲染以及网络的请求资源的下载将会变得非常缓慢,影响用户观感体验。这对于前端网站来说是十分致命的缺陷。

在当今互联网时代,用户体验已成为衡量网站质量的重要指标之一。随着网页内容的日益丰富,特别是图片资源的大量使用,如何高效且快速地展示页面成为了前端开发中不可忽视的挑战。其中,“图片懒加载”技术便是解决这一问题的有效手段,它不仅能够提升页面加载速度,还能显著改善用户体验。

懒加载到底做了什么?

简单来说其实懒加载做的事情就是只加载用户屏幕目前所需要的图片,这里可能不是特别准确,但是大致意思就是加载目前用户屏幕所展示的图片其他的图片不进行加载,只有当用户滑动页面的时候,其他图片进行判断加载(图片出现在用户屏幕中则进行加载

这里提一嘴,只要浏览器已经加载过的图片就会加入到缓存中,浏览器可以直接从缓存中加载图片,而不是每次都重新发起网络请求。

懒加载原理是什么呢?为什么懒加载能控制图片的加载呢?

这里就不得不聊聊图片的特性了,其实只要图片具有src属性,浏览器就会对该地址进行网络请求下载资源。懒加载就是通过判断加载(前面提过)然后给图片进行src赋值,浏览器就会自动发送网络请求给资源地址进行下载。

懒加载实例和实现讲解

其实懒加载就是两点需要注意

  1. 如何控制img属性src赋值,并且图片地址存放在哪
  2. 什么时候进行加载什么时候不进行加载

关于第一点我的实现是使用自定义属性data-srcdata-为前缀的属性是HTML5引入的一个特性,允许开发者在HTML元素上嵌入自定义的数据属性。这类属性为非标准的属性,提供了存储与元素相关的元数据的方式,而不会影响到HTML的语义结构。在JavaScript中,可以通过元素的dataset属性轻松访问这些自定义数据属性。
这样我们就可以先使用data-src存储图片的资源地址,等到图片应当加载的时候,再进行src的赋值。

第二点我通过画图来解释

image.png

代码实现详解

实现步骤主要分为以下几点:

  • 监听鼠标滚轮事件,因为只有鼠标进行滚动之后新的图片才有可能出现在屏幕中,所以这里我们进行鼠标滚轮监听,只要鼠标滚动进行了滚动我们就执行图片加载方法进行判断。

  • 图片什么时候加载,主要需要做两件事情,第一件事情就是,判断图片是否进入到了屏幕中,这里我用的是
    offsetTop属性,offsetTop 是一个JavaScript DOM属性,用于获取一个元素相对于其最近的具有定位(positioned)的父元素顶部的距离。如果元素的所有祖先元素都没有定位(默认的 position: static),那么 offsetTop 会返回元素相对于整个文档顶部的距离。


    这里只需要判断图片的offsetTop属性(距离文档顶部的距离)是否 <= 滚轮已经滚动的距离scrollTop+屏幕高度clientHeight。让我画个图- ̗̀(๑ᵔ⌔ᵔ๑)

image.png

第二件事情就是通过dataset对象属性拿到自定义属性进行src的赋值,这一步知道dataset后就非常简单。

下面是我的实例代码,大家可以直接复制然后使用。

<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><link rel="stylesheet" href="./common.css">
</head><body><img data-price="20" data-src="https://www.toopic.cn/public/uploads/image/20200407/20200407210607_94155.jpg" /><img data-src="https://www.toopic.cn/public/uploads/image/20200408/20200408214128_24416.jpg"><img data-src="https://www.toopic.cn/public/uploads/small/1704296749480170429674998.jpg"><img data-src="https://www.toopic.cn/public/uploads/small/1695608930939169560893045.jpg"><img data-src="https://www.toopic.cn/public/uploads/small/1642755454773164275545428.jpg"><img data-src="https://www.toopic.cn/public/uploads/image/20200411/20200411125828_78760.jpg"><img data-src="https://www.toopic.cn/public/uploads/image/20200409/20200409221455_72056.jpg"><img data-src="https://www.toopic.cn/public/uploads/image/20200407/20200407213848_17992.jpg"><img data-src="https://www.toopic.cn/public/uploads/image/20200405/20200405223436_89821.jpg"><img data-src="https://www.toopic.cn/public/uploads/image/20200411/20200411125228_17646.jpg"><img data-src="https://www.toopic.cn/public/uploads/image/20200407/20200407205944_99274.jpg"><img data-src="https://www.toopic.cn/public/uploads/image/20200411/20200411125355_54192.jpg"><img data-src="https://www.toopic.cn/public/uploads/image/20200404/20200404183643_27556.jpg"><img data-src="https://www.toopic.cn/public/uploads/image/20200407/20200407213757_91609.jpg"></body>
<script src="https://cdn.bootcdn.net/ajax/libs/lodash.js/4.17.21/lodash.min.js"></script>
<script>const imgs = document.querySelectorAll('img');const num = imgs.length;const screenHeight = document.documentElement.clientHeight;//一屏的高度let n = 0;document.addEventListener('DOMContentLoaded', () => {loadImage();})function loadImage() {console.log('1');// 是否在可视区?// 滚动条偏移量// 不同浏览器兼容性问题let scrollTop = document.documentElement.scrollTop || document.body.scrollTop;// console.log(screenHeight);for (let i = n; i < num; i++) {if (imgs[i].offsetTop < (scrollTop + screenHeight)) {// console.log(imgs[i].dataset);//数据属性imgs[i].src = imgs[i].dataset.src;// imgs[i].src = imgs[i].getAttribute('data-src');n = i + 1;if (n === num) {window.removeEventListener('scroll', throttleLayLoad);}}}}const throttleLayLoad = _.throttle(loadImage, 300);window.addEventListener('scroll', throttleLayLoad);loadImage();
</script></html>

防抖和节流

引言

其实防抖和节流非常相似,只是各自实现判断的条件不同。

首先我来介绍一下为什么需要防抖和节流,当你鼠标滚动的时候,触发监听事件的次数可能会有成百上千次相同的图片加载方法也会执行上千次,其实并不是每次滚动都需要加载图片的,因为一个图片的高度需要你滚一会儿才能滚完。所以我们只需要在滚动的一段时间内触发一次图片加载方法就可以了。

相同的是,
两个方法都是通过定时器进行指定时间内的图片加载。不同的如下:

  • 防抖:在一段时间内频繁触发的事件,只有在最后一次触发后的一段时间内没有再次触发,才会执行函数。
  • 节流:确保一个函数在规定时间内只执行一次,即使在这段时间内多次触发,也保持固定的执行频率。
防抖方法详解
function debounce(func, delay) {//定时器let timer = null;return function () {// 当前时间段还有定时任务(图片加载函数)正在等待执行,取消timer(定时函数)if (timer) clearTimeout(timer);// 重新进入新的时间等待或者是时间段内第一次触发,给timer重新赋值timer = setTimeout(function () {//图片加载函数imageLoad();}, 500)}}

这样子,只要我在一段时间之内一直滚动的话,触发的也只有最后一次滚动执行的定时任务(图片加载)

节流方法详解
function throttle(func, delay) {//定义一个定时器let timer = null;return function () {// 当前时间段内已经执行过一次滚轮事件了,触发了一次定时任务(图片加载),不再执行图片加载函数了if (timer) return;//只有函数执行完或者第一次执行则再次执行timer = setTimeout(function () {func();timer = null;}, delay)}}

规定一段时间内,只能执行一次图片加载,也就是定时任务(图片加载)期间不允许再次执行

结语

图片懒加载作为前端性能优化的一项重要策略,其核心在于平衡资源加载与用户体验之间的关系。通过深入理解浏览器的工作机制,合理利用数据属性和JavaScript监听事件,我们可以有效提升网页的加载速度和响应性。此外,掌握防抖与节流等高级技巧,更是优化前端逻辑、提升代码效率的关键。

喜欢的话就点个关注和赞吧!谢谢- ̗̀(๑ᵔ⌔ᵔ๑)

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

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

相关文章

热题系列章节6

297. 二叉树的序列化与反序列化 序列化是将一个数据结构或者对象转换为连续的比特位的操作&#xff0c;进而可以将转换后的数据存储在一个文件或者内存中&#xff0c;同时也可以通过网络传输到另一个计算机环境&#xff0c;采取相反方式重构得到原数据。 请设计一个算法来实现…

Android面试题精选——再聊Android-Handler机制

​ static final ThreadLocal sThreadLocal new ThreadLocal(); //创建当前线程的Looper对象 private static void prepare(boolean quitAllowed) { if (sThreadLocal.get() ! null) { throw new RuntimeException(“Only one Looper may be created per thread”); } sThre…

华为欧拉 openEuler24.03 更新 阿里 yum源

华为欧拉 openEuler24.03 更新 阿里 yum源 备份 yum 源编写 阿里云 yum源 配置文件更新 yum 缓存 备份 yum 源 mv /etc/yum.repos.d/openEuler.repo /etc/yum.repos.d/openEuler.repo.bak编写 阿里云 yum源 配置文件 vim /etc/yum.repos.d/openEuler.repo内容如下&#xff…

【进阶篇-Day5:JAVA常用API的使用(Math、BigDecimal、Object、包装类等)】

目录 1、API的概念2、Object类2.1 Object类的介绍2.2 Object的toString()方法2.3 Object的equals()方法2.4 Objects概述 3、Math类4、System类5、BigDecimal类6、包装类6.1 包装类的概念6.2 几种包装类&#xff08;1&#xff09;手动转换包装类&#xff1a;&#xff08;2&#…

pg分区表和mysql分区表的创建及删除添加操作

一、分区的类型 1、pg分区的类型 范围划分 列表划分 哈希分区 2、mysql分区的类型 范围分区 列表分区 hash分区 列分区 密匙分区 子分区 二、pg范围分区表的创建删除添加操作 1、pg分区表的创建 2、pg的分区表删除 3、pg分区表的添加 创建新的子分区 添加新创建的子分区 …

python 字符串驻留机制

偶然发现一个python字符串的现象&#xff1a; >>> a 123_abc >>> b 123_abc >>> a is b True >>> c abc#123 >>> d abc#123 >>> c is d False 这是为什么呢&#xff0c;原来它们的id不一样。 >>> id(a)…

浙大宁波理工学院2024年成人高等继续教育招生简章

浙大宁波理工学院&#xff0c;这所承载着深厚学术底蕴和卓越教育理念的学府&#xff0c;正热烈开启2024年成人高等继续教育的招生之门。这里&#xff0c;是知识的殿堂&#xff0c;是智慧的摇篮&#xff0c;更是您实现个人梦想、追求更高境界的起点。 ​浙大宁波理工学院始终坚…

实战指南:部署Elasticsearch 8.4.1与Kibana 8.4.1并集成IK分词器

首先拉取elasticsearch和kibana镜像 docker pull elasticsearch:8.4.1 docker pull kibana:8.4.1如果遇到镜像拉去不下来&#xff0c;遇到如下问题&#xff1a; [ERROR] error pulling image configuration: Get " https://production.cloudflare.docker.com/registry-v…

【吊打面试官系列-Mysql面试题】视图有哪些优点?

大家好&#xff0c;我是锋哥。今天分享关于 【视图有哪些优点&#xff1f;】面试题&#xff0c;希望对大家有帮助&#xff1b; 视图有哪些优点&#xff1f; 答&#xff1a; (1) 视图能够简化用户的操作&#xff1b; (2) 视图使用户能以多种角度看待同一数据&#xff1b; (3) 视…

【C#】使用数字和时间方法ToString()格式化输出字符串显示

在C#编程项目开发中&#xff0c;几乎所有对象都有格式化字符串方法&#xff0c;其中常见的是数字和时间的格式化输出多少不一样&#xff0c;按实际需要而定吧&#xff0c;现记录如下&#xff0c;以后会用得上。 文章目录 数字格式化时间格式化 数字格式化 例如&#xff0c;保留…

【docker1】指令,docker-compose,Dockerfile

文章目录 1.pull/image&#xff0c;run/ps&#xff08;进程&#xff09;&#xff0c;exec/commit2.save/load&#xff1a;docker save 镜像id&#xff0c;不是容器id3.docker-compose&#xff1a;多容器&#xff1a;宿主机&#xff08;eth0网卡&#xff09;安装docker会生成一…

4、SpringMVC 实战小项目【加法计算器、用户登录、留言板、图书管理系统】

SpringMVC 实战小项目 3.1 加法计算器3.1.1 准备⼯作前端 3.1.2 约定前后端交互接⼝需求分析接⼝定义请求参数:响应数据: 3.1.3 服务器代码 3.2 ⽤⼾登录3.2.1 准备⼯作3.2.2 约定前后端交互接⼝3.2.3 实现服务器端代码 3.3 留⾔板实现服务器端代码 3.4 图书管理系统准备后端 3…

【电路笔记】-共发射极放大器

共发射极放大器 文章目录 共发射极放大器1、概述2、完整的CEA配置3、直流等效电路4、交流等效电路5、输入阻抗6、输出阻抗7、电压增益8、微分电容的重要性9、信号源的衰减10、电流增益11、相位反转12、总结1、概述 在本文中,我们将介绍基于双极晶体管的放大器的最后一种拓扑:…

2024 WaniCTF repwn 部分wp

lambda 文本编辑器打开附件 稍微格式化一下 结合gpt理解题目意思。 脚本 home 附件拖入ida 简单的检查环境和反调试&#xff0c;进构造flag的函数 简单的ollvm&#xff0c;用d810嗦一下 下断点调试&#xff0c;通过修改eip跳过反调试。查看dest内容&#xff0c;需要稍微向下翻一…

QT中利用动画弄一个侧边栏窗口,以及贴条效果

1、效果 2、关键代码 void Widget::on_sliderBtn_clicked() {m_sliderWidget->show();QPropertyAnimation* animation = new QPropertyAnimation(m

第14章. GPIO简介

目录 0. 《STM32单片机自学教程》专栏 14.1 GPIO基本结构 14.1.1 保护二极管 14.1.2 上拉、下拉电阻 14.1.3 施密特触发器 14.1.4 P-MOS 管和 N-MOS 管 14.1.5 输出数据寄存器 14.1.6 输入数据寄存器 14.2 GPIO工作模式 14.2.1 输入模式 14.2.1.1 输入浮空模式 1…

ABB机器人教程:工具载荷与有效载荷数据自动标定操作方法

目录 概述 工具载荷自动标定前的准备工作 进入载荷识别服务例行程序 工具载荷识别与标定操作 有效载荷识别与标定操作要点 4轴码垛类型机器人载荷数据标定说明 概述 在使用ABB机器人前需要正确标定一些关键数据&#xff0c;其中就包含载荷数据。理论上讲&#xff0c;安装…

issues.sonatype.org网站废弃,Maven仓库账号被废弃问题解决

问题起因&#xff1a; 今天自己的项目发布了一个新版本&#xff0c;打算通过GitHub流水线直接推送至Maven中央仓库&#xff0c;结果发现报错 401&#xff0c;说我的账号密码认证失败。我充满了疑惑我寻思难度我的号被盗掉了吗。于是我打开Nexus Repository Manager尝试登录账号…

【b站-湖科大教书匠】2 物理层-计算机网络微课堂

课程地址&#xff1a;【计算机网络微课堂&#xff08;有字幕无背景音乐版&#xff09;】 https://www.bilibili.com/video/BV1c4411d7jb/?share_sourcecopy_web&vd_sourceb1cb921b73fe3808550eaf2224d1c155 目录 2 物理层 2.1 物理层的基本概念 2.2 物理层下面的传输媒…

Android Studio 安卓手机上实现火柴人动画(Java源代码—Python)

android:layout_marginLeft“88dp” android:layout_marginTop“244dp” android:text“Python” android:textSize“25sp” app:layout_constraintStart_toStartOf“parent” app:layout_constraintTop_toTopOf“parent” /> </androidx.constraintlayout.widget.…