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

前言

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

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

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监听事件,我们可以有效提升网页的加载速度和响应性。此外,掌握防抖与节流等高级技巧,更是优化前端逻辑、提升代码效率的关键。

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

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Java宝藏实验资源库(2)字节流

一、实验目的 掌握输入输出流的基本概念。掌握字节流处理类的基本结构。掌握使用字节流进行输入输出的基本方法。 二、实验内容、过程及结果 *17.10 (Split files) Suppose you want to back up a huge file (e.g., a 10-GB AVI file) to a CD-R. You can achieve it by split…

计算机毕业设计Python+Vue.js+Flask+Scrapy电影大数据分析 电影推荐系统 电影爬虫可视化 电影数据分析 大数据毕业设计 协同过滤算法

开发技术 协同过滤算法、机器学习、vue.js、echarts、Flask、Python、MySQL 创新点 协同过滤推荐算法、爬虫、数据可视化 补充说明 两种Python协同过滤推荐算法集成 (ItemCF推荐算法 和 UserCF 推荐算法) 2.专业美工整体设计的细腻的酷黑主题&#xff0c;前后端分离一体化系统&…

Opencv学习项目1——pytesseract

最近开始学习opencv使用&#xff0c;跟着b站一起做实战项目&#xff0c;跟大家分享一下学习成果&#xff0c;大佬勿喷 项目演示 pytesseract 是一个用于文字识别&#xff08;OCR&#xff0c;光学字符识别&#xff09;的 Python 库&#xff0c;它是 Tesseract OCR 引擎的 Python…

探究 IP 地址被网站封禁的原因

在我们登录各种网站、APP浏览时&#xff0c;可能会遇到 IP 地址被某些网站封禁的情况。很多人奇怪这是为什么呢&#xff1f; 首先&#xff0c;违反网站的使用规则是比较常见的原因之一。比如&#xff0c;频繁发送垃圾邮件、恶意评论、进行网络攻击或试图破解网站的安全机制等不…

关于Windows系统下redis的闪退问题。

一、问题分析 首先&#xff0c;有这个问题的一般是如下操作&#xff1a; 1、在运行项目时发现无法连接到redis服务器&#xff0c; 2、进入Redis安装目录(如图)——>鼠标双击打开redis-server.exe&#xff0c;然后闪退&#xff0c; 3、运行redis-cli时提示&#xff1a;“由…

kafka学习笔记07

Kafka高可用集群搭建节点需求规划 开放端口。 Kafka高可用集群之zookeeper集群搭建环境准备 删除之前的kafka和zookeeper。 重新进行环境部署&#xff1a; 我们解压我们的zookeeper: 编辑第一个zookeeper的配置文件: 我们重复类似的操作&#xff0c;创建三个zookeeper节点: 记…

Android Glide, first start based on loadThumbnail, Kotlin(二)

Android Glide, first start based on loadThumbnail, Kotlin&#xff08;二&#xff09; Android Glide, first start based on loadThumbnail, Kotlin&#xff08;一&#xff09;中有个小问题&#xff0c;通过loadThumbnail()采集到的缩略图真的就是整张图片的完整缩略图&…

PTP简介及Linux phy ptp驱动实现

1、PTP简介 PTP(precision time protocol)精确时间协议&#xff0c;是一种时间同步的协议&#xff0c;对应 IEEE 1588 标准&#xff0c;是基于网络数据包的一种时间同步协议&#xff0c;1588v2的同步精度可以达到ns级&#xff0c;但1588协议对硬件有依赖。 2、PTP原理 时间同…

Part 6.2.3 欧拉函数

欧拉函数φ(x) 表示了小于x的数字中&#xff0c;与x互质的数字个数。 关于欧拉函数的基本知识>欧拉函数的求解< [SDOI2008] 仪仗队 题目描述 作为体育委员&#xff0c;C 君负责这次运动会仪仗队的训练。仪仗队是由学生组成的 N N N \times N NN 的方阵&#xff0c;…

使用Docker在Mac上部署OnlyOffice,预览编辑word、excel、ppt非常好

前端编辑word、ppt文档&#xff0c;开源免费方案并没有找到合适的&#xff0c;像wps、石墨文档都是自研的方案。实现过程中wps采用的svg方案&#xff0c;而石墨文档采用的是canvas&#xff0c;它们均是自己来实现编辑器&#xff0c;不依赖浏览器提供的编辑器&#xff08;conten…

如何用python调用C++处理图片

一. 背景 用pyhton可直接调用C&#xff0c;减少重写的工作量&#xff1b;部分逻辑运算&#xff0c;C的执行效率高&#xff0c;可进行加速。 下面就一个简单的C滤镜&#xff08;彩色图转灰度图&#xff09;为例&#xff0c;展示python调用C 二. 代码实现 代码结构如下&#x…

Windows桌面运维----第四天

1、U盘故障打不开&#xff1a; 操作方式&#xff1a;WinR打开运行&#xff0c;输入cmd确定&#xff0c;在&#xff08;C:\Users\Administrator>&#xff09;后输入chkdsk,空格&#xff0c;输入U盘盘符&#xff0c;例如F:/F&#xff0c;回车&#xff0c;等待修复完成。 2、…

韩国裸机云站群服务器托管租用方案

随着网络技术的飞速发展&#xff0c;站群服务器在网站运营中扮演着越来越重要的角色。韩国裸机云站群服务器&#xff0c;以其独特的优势&#xff0c;如地理位置优越、价格相对较低、技术实力雄厚等&#xff0c;吸引了众多企业的关注。本文将为您详细介绍韩国裸机云站群服务器的…

【TB作品】MSP430G2553,单片机,口袋板, 现场数据采集装置设计

题2 现场数据采集装置设计 便携式数据采集装置将在现场采集到的数据装入装置的内部数存贮器&#xff0c;以待送实验室或试验中心的计算机进行分析处理&#xff0c;由于现场不一定有交流电供电&#xff0c;而且采集到的数据必须保存到送实验室&#xff0c;因此装置必须以电池或蓄…

红米手机RedNot11无法使用谷歌框架,打开游戏闪退的问题,红米手机如何开启谷歌框架

红米手机RedNot11无法使用谷歌框架&#xff0c;打开游戏闪退的问题&#xff0c; 1.问题描述2.问题原因3.解决方案3.1配置谷歌框架&#xff1a;3.1软件优化 4.附图 1.问题描述 红米手机打开安卓APP没有广告&#xff0c;直接闪退&#xff0c;无法使用谷歌框架 异常关键词中包含&…

NavicatforMySQL11.0软件下载-NavicatMySQL11最新版下载附件详细安装步骤

我们必须承认Navicat for MySQL 支援 Unicode&#xff0c;以及本地或远程 MySQL 服务器多连线&#xff0c;使用者可浏览数据库、建立和删除数据库、编辑数据、建立或执行 SQL queries、管理使用者权限&#xff08;安全设定&#xff09;、将数据库备份/复原、汇入/汇出数据&…

SAS副总裁Jason Mann:物联网如何让世界变得更美好

TechForge最近采访了数据和人工智能领导者 SAS的物联网副总裁 Jason Mann &#xff0c;他解释了公司如何有效利用物联网&#xff0c;以及该技术如何改善全球的可持续性。 您认为今年物联网领域的最新发展趋势是什么&#xff1f; 一个主要趋势是GenAI的不断涌现&#xff0c;这进…

计算机网络:运输层 - TCP 流量控制 拥塞控制

计算机网络&#xff1a;运输层 - TCP 流量控制 & 拥塞控制 滑动窗口流量控制拥塞控制慢开始算法拥塞避免算法快重传算法快恢复算法 滑动窗口 如图所示&#xff1a; 在TCP首部中有一个窗口字段&#xff0c;该字段就基于滑动窗口来辅助流量控制和拥塞控制。所以我们先讲解滑…

Spark Core内核调度机制详解(第5天)

系列文章目录 如何构建DAG执行流程图 (掌握)如何划分Stage阶段 (掌握)Driver底层是如何运转 (掌握)确定需要构建多少分区(线程) (掌握) 文章目录 系列文章目录引言一、Spark内核调度&#xff08;掌握&#xff09;1.1、内容概述1.2、RDD的依赖1.3、DAG和Stage1.4、Spark Shuffl…

Flink 1.19.1 standalone 集群模式部署及配置

flink 1.19起 conf/flink-conf.yaml 更改为新的 conf/config.yaml standalone集群: dev001、dev002、dev003 config.yaml: jobmanager address 统一使用 dev001&#xff0c;bind-port 统一改成 0.0.0.0&#xff0c;taskmanager address 分别更改为dev所在host dev001 config.…