不是哥们?你怎么抖成这样了?求你进来学学防抖吧!全方位深入剖析防抖的奥秘

news2024/11/13 9:27:35

前言

古有猴哥三打白骨精,白骨精 ======> 噶

今有用户疯狂点请求,服务器 ======> 噶

所以这防抖咱必须得学会!!!

本文就来讲解一下Web前端中防抖的奥秘吧!!!!

为什么要做防抖

在一些功能中,需要向服务器发送请求来获取数据。如果用户在短时间内疯狂的去点击触发这个功能,就会导致大量的请求被发送到服务器,造成资源浪费,同时也会使页面频繁刷新数据,降低用户的体验。

在这种情况下,使用防抖就显得非常重要了

防抖可以限制函数的执行频率,只在事件触发的间隔期之后执行一次

具有以下的效果:

  1. 提高页面性能: 减少不必要的函数调用,降低页面负载。
  2. 优化用户体验: 避免页面频繁刷新,让交互更加流畅。
  3. 减轻服务器压力: 减少无谓的网络请求,降低服务器的负担。

防抖代码详解

未防抖

首先我们分析以下的代码的执行结果是什么?

var btn = document.getElementById('btn');

btn.addEventListener('click', function(){
        console.log("提交")
    )
}

首先通过document.getElementById('btn') 方法获取了页面中 idbtn 的元素

使用 addEventListener 方法为该元素添加了一个点击事件监听。

当用户点击这个元素时,会执行console.log("提交") 输出字符串 "提交"

动画.gif

我们可以看到,由于按钮并没有做防抖处理,当我们疯狂点击提交按钮时,就会使得函数被疯狂的调用

这显然是不行的,哒咩哒咩!!!!!!

防抖

接下来我们开始去实现防抖效果了

首先分析一下防抖是一个怎么样的效果呢?

简单来说就是在规定的时间内没有下一次的触发,就执行函数

那么我们要怎么样去实现这个效果呢????

于是我们就想到了定时器触发执行函数,当我们在规定时间内没有触发,定时器就正常的去执行了函数,如果触发了,我们就把原先的定时器删了,创建一个新的定时器,这样我们不就实现了防抖,说干就干!

var btn = document.getElementById('btn');

function handle() {
    console.log('提交');
}
        
btn.addEventListener('click', debounce(handle))

//防抖函数
function debounce(fn) {
    let timer = null;
    //这是一个闭包
    return function () {
        //如果第二次的时间没到一秒就销毁上一次的计时器
        clearTimeout(timer)
        timer = setTimeout(fn, 1000)
    }
}

这段代码通过使用闭包和 setTimeout 的方式,实现了一个简单而实用的防抖功能。当用户在 1 秒内连续触发事件时,只有在 1 秒的间隔后才会执行一次 handle 函数,从而避免了不必要的重复操作。

如果还不是很了解什么是闭包的小伙伴可以先读一下这篇文章面试官:JavaScript执行机制中的闭包? - 掘金 (juejin.cn)

动画.gif

可以看到这段代码已经帮我们实现了防抖的效果了,但是这段代码是有不足之处的,我们继续讲解

这里我们会提到this的指向问题,对于不是很了解的小伙伴也可以先看看这篇文章了解一下this探索 JavaScript “this”指向的内在逻辑 - 掘金 (juejin.cn)

如果我们执行一下代码,结果是如何?

var btn = document.getElementById('btn');

function handle() {
    console.log(this);
}
btn.addEventListener('click', handle)

可以看到结果为btn

image.png

由于addEventListener决定handle的执行,所以addEventListener干扰了this,让this不指向全局

这里我们可以想到一个防抖函数肯定是不能说去改变了原有的this指向的

可是我们这里却改变了this的指向

var btn = document.getElementById('btn');

function handle() {
    console.log('提交', this);
}

btn.addEventListener('click', debounce(handle))

function debounce(fn) {
    let timer = null;
    return function () {
        clearTimeout(timer)
        timer = setTimeout(() => {  
            fn()
        }, 1000)
    }
}

可以看到this的指向变为了win

image.png

我们需要将指向修正回来

这里我们可以看到addEventListener决定执行的函数不再是handle而是我们的防抖函数debounce,所以很显然,debounce返回的函数里面的this才是我们想要的this,我们只需要将handle里的this指向debounce返回的函数里的this即可完成修正

var btn = document.getElementById('btn');

function handle(e) {
    console.log(this);
}

btn.addEventListener('click', debounce(handle))

function debounce(fn) {
    let timer = null;
    return function () {
        clearTimeout(timer)
        timer = setTimeout(() => {
            // this就是一个对象
            fn.call(this)
        }, 1000)
    }
}

此时handle的this就是正确的了

image.png

但是这里还有一个问题,addEventListener的回调函数会接收一个事件对象 e。这个事件对象包含了事件的相关信息,比如触发事件的元素、鼠标/键盘事件的坐标等

但是由于现在使用了防抖函数的原因,就使得e丢失了,在handle里面没有了e,而这个事件对象也在function里面,我们需要把他也传给handle

接下来修改代码

var btn = document.getElementById('btn');

function handle(e) {
    console.log(e);
    console.log(this);
}

btn.addEventListener('click', debounce(handle))

function debounce(fn) {
    let timer = null;
    return function (e) {
        clearTimeout(timer)
        timer = setTimeout(() => {
            fn.call(this, e)
        }, 1000)
    }
}

这样我们就实现了完整的防抖函数

image.png

总结

本文全方位深入剖析防抖的奥秘,通过结合代码以及其实现效果,由浅入深得讲解防抖的全部实现流程

希望能够帮助到你,如果对你有所帮助,别忘了一键三连,点赞、收藏加评论呦~

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

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

相关文章

2-27 基于matlab的一种混凝土骨料三维随机投放模型

基于matlab的一种混凝土骨料三维随机投放模型,为混凝土细观力学研究提供一种快捷的三维建模源代码。可设置骨料数量,边界距离、骨料大小等参数。程序已调通,可直接运行。 2-27 matlab 混凝土骨料三维随机投放模型 - 小红书 (xiaohongshu.com)…

盘点8款国内顶尖局域网监控软件(2024年国产局域网监控软件排名)

局域网监控软件对于企业网络管理至关重要,它们可以帮助IT部门维护网络安全,优化网络性能,同时监控和控制内部员工的网络使用行为。以下是八款备受推崇的局域网监控软件,每一款都有其独特的优势和适用场景。 1.安企神软件 试用版领…

CompletionService

必备知识: 三种创建线程的方式 java线程池 CompletionService是Java并发库中的一个接口,用于简化处理一组异步任务的执行和结果收集。它结合了Executor和BlockingQueue的功能,帮助管理任务的提交和完成。CompletionService的主要实现类是Exe…

python破解字母已知但大小写未知密码

python穷举已知字符串中某个或多个字符为大写的所有情况 可以使用递归函数来实现这个功能。以下是一个示例代码: def generate_uppercase_combinations(s, index0, current):if index len(s):print(current)returngenerate_uppercase_combinations(s, index 1, …

如何保证接口幂等性

如何保证接口幂等性 1、幂等性是什么? 接口幂等性是指用户对于同一操作发起的一次请求或者多次请求的结果是一致的,不会因为多次点击而产生了不同的结果。 2、使用幂等性的场景有哪些? 页面点击保存按钮时,不小心快速点了两次…

BUUCTF[PWN][fastbin attack]

fastbin_attack例题 题目:[BUUCTF在线评测 (buuoj.cn)](https://buuoj.cn/challenges#[ZJCTF 2019]EasyHeap) 整体思路:利用编辑时edit_heap函数的栈溢出漏洞,覆盖heaparray中的栈指针指向free的got表,将其改为system的plt表&…

Bert入门-使用BERT(transformers库)对推特灾难文本二分类

Kaggle入门竞赛-对推特灾难文本二分类 这个是二月份学习的,最近整理资料所以上传到博客备份一下 数据在这里:https://www.kaggle.com/competitions/nlp-getting-started/data github(jupyter notebook):https://gith…

C语言指针函数指针

跟着这篇文章重新理解了一下:彻底攻克C语言指针 有一个例子感觉可以拿出来看看: char *(*c[10])(int **p); * 这段声明定义了一个长度为10的数组c,数组中的每个元素都是指向函数的指针。每个函数接受一个类型为int **(指向指向…

【SpringCloud应用框架】Nacos集群架构说明

第六章 Spring Cloud Alibaba Nacos之集群架构说明 文章目录 前言一、Nacos支持三种部署模式二、集群部署说明三、预备环境 前言 到目前为止,已经完成了对Nacos的一些基本使用和配置,接下来还需要了解一个非常重要的点,就是Nacos的集群相关的…

用PlantUML和语雀画UML类图

概述 首先阐述一下几个简单概念: UML:是统一建模语言(Unified Modeling Language)的缩写,它是一种用于软件工程的标准化建模语言,旨在提供一种通用的方式来可视化软件系统的结构、行为和交互。UML由Grady…

一.7.(2)基本运算电路,包括比例运算电路、加减运算电路、积分运算电路、微分电路等常见电路的分析、计算及应用;(未完待续)

what id the 虚短虚断虚地? 虚短:运放的正相输入端和反相输入端貌似连在一起了,所以两端的电压相等,即UU- 虚断:输入端输入阻抗无穷大 虚地:运放正相输入端接地,导致U=U-=0。 虚…

远心镜头简介

一、远心镜头 大家都有这种印象,一个物体在人眼看来,会有近大远小的现象。这是因为物体近的时候,在视网膜上投影大,小的时候,投影小。镜头也是一样,因为近大远小的原因,会产生误差。特别是在做尺…

通信协议_Modbus协议简介

概念介绍 Modbus协议:一种串行通信协议,是Modicon公司(现在的施耐德电气Schneider Electric)于1979年为使用可编程逻辑控制器(PLC)通信而发表。Modbus已经成为工业领域通信协议的业界标准(De f…

Java里的Arrary详解

DK 中提供了一个专门用于操作数组的工具类,即Arrays 类,位于java.util 包中。该类提供了一些列方法来操作数组,如排序、复制、比较、填充等,用户直接调用这些方法即可不需要自己编码实现,降低了开发难度。 java.util.…

DC-DC充放电原理

文章目录 前言1. 电子器件1.1 电容1.2 电感 2. 升压电路3. 降压电路4. 电压均衡电路4.1 被动均衡4.2 主动均衡 5. 我的疑问5.1 对于升压电路,怎么设计升压到多少V后,停止升压?5.2 什么是等效电阻?5.3 快充是如何实现的&#xff1f…

探索InitializingBean:Spring框架中的隐藏宝藏

​🌈 个人主页:danci_ 🔥 系列专栏:《设计模式》《MYSQL》 💪🏻 制定明确可量化的目标,坚持默默的做事。 ✨欢迎加入探索MYSQL索引数据结构之旅✨ 👋 Spring框架的浩瀚海洋中&#x…

ISP和IAP原理解释

ISP和IAP ISP ISP的全称是:In System Programming,即在系统编程,该操作是通过MCU厂商出厂BootLoader来实现,通过ISP可以对主flash区域进行擦除、编程操作,还可以修改芯片的选项字节等。例如,GD32F30x用户…

Failed to get D-Bus connection: Operation not permitted

最近使用wsl安装了centOS7镜像,在系统中安装了docker服务,但是在执行systemctl start docker的时候遇到了:Failed to get D-Bus connection: Operation not permitted问题,查阅了很多资料都没有效果,最终找到了一种解决…

RabbitMQ(集群相关部署)

RabbitMQ 集群部署 环境准备:阿里云centos8 服务器,3台服务器,分别进行安装; 下载Erlang Erlang和RabbitMQ版本对照:https://www.rabbitmq.com/which-erlang.html 创建yum库配置文件 vim /etc/yum.repos.d/rabbi…

【web前端HTML+CSS+JS】--- CSS学习笔记02

一、CSS(层叠样式表)介绍 1.优势 2.定义解释 如果有多个选择器共同作用的话,只有优先级最高那层样式决定最终的效果 二、无语义化标签 div和span:只起到描述的作用,不带任何样式 三、标签选择器 1.标签/元素选择器…