防抖和节流的实现

防抖和节流的实现

  • 什么是防抖和节流
  • 实现防抖和节流
    • 防抖
    • 节流
  • 防抖和节流的应用场景

什么是防抖和节流

防抖和节流是前端开发中常用的两种性能优化技术。

为什么需要防抖和节流呢?

两者目的都是为了防止某个时间段内操作频繁触发,造成性能消耗。

防抖:在事件被触发 n 秒后再执行回调,如果在这 n 秒内事件又被触发,则重新计时。

节流: n 秒内只执行一次事件,即使n 秒内事件重复触发,也只有一次生效。

可能很多人看了概念还是不太清楚这两者到底有什么区别,下面就通过一个简单的案例来说明。

let btn = document.getElementById('btn')
//模拟发送请求
function req(){console.log('发送请求')
}
btn.addEventListener('click', req)

以上代码简单实现了一个点击按钮的事件,每点击一次按钮就调用一次函数发送请求,效果如下:

在这里插入图片描述
如果对函数做了防抖(时间设为1秒),效果是下面这样的:

在这里插入图片描述
1秒内不管点击了多少次按钮,事件都不会被触发,只有当不再点击按钮后,过了1秒,事件才被触发。

如果对函数做了节流(时间设为1秒),效果是下面这样的:

在这里插入图片描述
1秒内不管点击了多少次按钮,事件都只被触发一次。

因此,两者的区别:防抖是一段时间内只执行最后一次,节流是一段时间内只执行一次。

如下图所示:
在这里插入图片描述

实现防抖和节流

防抖

实现思路:使用闭包来保存定时器变量 timer。事件触发后开启一个定时器,如果在 delay 时间内再次触发事件,就会清除之前的定时器

并设置一个新的定时器,直到 delay 时间内不再触发事件,定时器到达时间后执行传入的函数 fn。

function debounce(fn, delay = 1000) {let timer = null;// 这里返回的函数是每次用户实际调用的防抖函数return function(...args) {	// 如果已经设定过定时器了就清空上一次的定时器if(timer) {clearTimeout(timer);	}// 开始一个新的定时器,延迟执行用户传入的方法timer = setTimeout(() => {  //这里必须是箭头函数,不然this指向window,要让this指向fn的调用者fn.apply(this, args);   }, delay)	}
}

节流

实现思路:同样使用闭包来保存定时器变量 timer。每次触发事件时,如果定时器不存在,就设置一个定时器,并在 delay 时间后执行传

入的函数 fn。如果在 delay 时间内再次触发事件,由于定时器还存在,就不会执行传入的函数 func。

function throttle(fn, delay = 500) {let timer = null;return function(...args) {// 当前有任务了,直接返回if(timer) {return;}timer = setTimeout(() => {fn.apply(this, args);timer = null;	//执行完后,需重置定时器,不然timer一直有值,无法开启下一个定时器}, delay)}
}

节流还有一种更简单的时间戳版本,思路就是两次触发的时间间隔到了指定时间就执行,否则不执行。

function throttle(fn, delay = 1000) {let prev = Date.now();// 上一次执行该函数的时间return function(...args) {let now = Date.now();//当前时间// 如果差值大于等于设置的等待时间就执行函数if (now - prev >= delay) {fn.apply(this, args);prev = Date.now();}};
}

防抖和节流的应用场景

防抖的主要应用场景是优化搜索框的输入,用户在不断输入值时,用防抖来节约请求资源,当用户最后一次输入完,再发送请求。

// 使用防抖优化搜索框输入
const searchInput = document.getElementById('input');
function req() {// 发送请求获取搜索结果console.log('发送请求...');
}
searchInput.addEventListener('keyup', debounce(req, 500));

节流的主要应用场景是优化滚动事件,当用户滚动页面时,会频繁触发滚动事件。使用节流函数可以控制滚动事件的触发频率,避免过多的计算和渲染操作,提高页面的性能和流畅度。

// 使用节流优化滚动事件
window.addEventListener('scroll', throttle(function() {// 滚动到底部加载更多console.log('加载更多...');
}, 500));

以上就是本文的分享了,如有错误,欢迎指正!

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

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

相关文章

NAT+ACL+mstp小综合

三、实验一相关知识点 1,实验:NAT 综合实验 2,拓扑: 3,需求: 1),实现VLAN20 的除了20这台主机以外所有主机上网访问外网 2),实现VLAN30 的主机为奇数电脑上网 3&#…

如何使用 Hotshot 通过文字生成 GIF 动画

Hotshot 是一个基于人工智能的工具,可用于通过文字生成 GIF 动画。该工具使用最新的图像生成技术来创建逼真的动画,即使是复杂的文字描述也能做到。 hotshot访问地址 使用 Hotshot 生成 GIF 动画 要使用 Hotshot 生成 GIF 动画,您需要首先…

FreeRTOS入门教程(队列详细使用示例)

文章目录 前言一、队列基本使用二、如何分辨数据源三、传输大块数据总结 前言 上篇文章我们已经讲解了队列的概念和队列相关的API函数,那么本篇文章的话就开始带大家来学习使用队列。 一、队列基本使用 这个例子将会创建三个任务,其中两个任务用来发送…

vue.js 生命周期

在页面首次加载执行顺序有如下: beforeCreate //在实例初始化之后、创建之前执行created //实例创建后执行beforeMounted //在挂载开始之前调用filters //挂载前加载过滤器computed //计算属性directives-bind //只调用一次,在指令第一次绑定到元素时调…

Leetcode 151. 反转字符串中的单词 JS版两种方法(内置API,双指针)有详细讲解 小白放心食用

🎶Leetcode 151. 反转字符串中的单词 难度:中等 ✨题目描述: 给你一个字符串 s ,请你反转字符串中 单词 的顺序。 单词 是由非空格字符组成的字符串。s 中使用至少一个空格将字符串中的 单词 分隔开。 返回 单词 顺序颠倒且 …

吃鸡高手亲授:玩转绝地求生,分享顶级游戏干货!

绝地求生(PUBG)自上线以来,成为了全球热门游戏。作为吃鸡行家,我将分享一些独家技巧和干货,帮助您提高游戏战斗力,享受顶级游戏作战体验! 首先,让我们谈一谈战斗力升级。想要在吃鸡游…

zabbix监控

目录 一、zabbix概述 1.zabbix是什么? 二、zabbix主要功能: 三.zabbix监控原理 四、zabbix监控对象(常用的监控程序) 五、zabbix监控模式: 六、zabbix监控架构 七、部署zabbix 一、zabbix概述 1.zabbix是什么? zabbix是一…

基于最近电平逼近的开环MMC逆变器Simulink仿真模型

💥💥💞💞欢迎来到本博客❤️❤️💥💥 🏆博主优势:🌞🌞🌞博客内容尽量做到思维缜密,逻辑清晰,为了方便读者。 ⛳️座右铭&a…

基于SpringBoot的民宿在线预定平台

目录 前言 一、技术栈 二、系统功能介绍 用户信息管理 民宿信息管理 民宿资讯管理 民宿分类管理 用户注册 民宿信息 我的订单 三、核心代码 1、登录模块 2、文件上传模块 3、代码封装 前言 随着信息技术在管理上越来越深入而广泛的应用,管理信息系统的实…

【RabbitMQ】初识消息队列 MQ,基于 Docker 部署 RabbitMQ,探索 RabbitMQ 基本使用,了解常见的消息类型

文章目录 前言一、初识消息队列 MQ1.1 同步通信1.2 异步通信1.3 MQ 常见框架及其对比 二、初识 RabbitMQ2.1 什么是 RabbitMQ2.2 RabbitMQ 的结构 三、基于 Docker 部署 RabbitMQ四、常见的消息类型五、示例:在 Java 代码中通过 RabbitMQ 发送消息5.1 消息发布者5.2…

数据结构 2.1 单链表

1.单链表 线性表:1.有限的序列 2.序列中的每一个元素都有唯一的前驱和后继,除了开头和结尾的两个节点。 顺序表:分配一块连续的内存去存放这些元素,eg、数组 链表:内存是不连续的,元素会各自被分配一块内…

吃鸡高手必备工具大揭秘!提高战斗力,分享干货,一站满足!

大家好!你是否想提高吃鸡游戏的战斗力,分享顶级的游戏作战干货,方便进行吃鸡作图和查询装备皮肤库存?是否也担心被骗,希望查询游戏账号是否在黑名单上,或者查询失信人和VAC封禁情况?在这段视频中…

ALSA pcm接口的概念解释

PCM(数字音频)接口 PCM缩写: Pulse Code Modulation脉冲调制编码,我们理解为通过一定连续时间周期产生数字音频并带有音量样本的处理过程. 模拟信号被记录通过模拟到数字转换器,数字值(也就是某个特定时刻的音量值)获得来自ADC可以进一步处理,接下的图片展示的是个sine wavefor…

Unity基于种子与地块概率的开放世界2D地图生成

public class BuildingGen : MonoBehaviour {public int[] Building;//存储要生成的地块代码public int[] Probability;//存储概率public double seed;public int width 100;public int height 100;public float noiseScale 0.1f; //噪声缩放倍数private int[,] frequencyM…

【C++设计模式之建造者模式:创建型】分析及示例

简介 建造者模式(Builder Pattern)是一种创建型设计模式,它将复杂对象的构建过程与其表示分离,使得同样的构建过程可以创建不同的表示。 描述 建造者模式通过将一个复杂对象的构建过程拆分成多个简单的部分,并由不同…

【MySQL】表的基础增删改查

前面我们已经知道怎么来创建表了,接下来就来对创建的表进行一些基本操作。 这里先将上次创建的表删除掉: mysql> use test; Database changedmysql> show tables; ---------------- | Tables_in_test | ---------------- | student | -----…

AI:08-基于深度学习的车辆识别

随着汽车行业的迅速发展,车型识别在交通管理、智能驾驶和车辆安全等方面变得越来越重要。基于深度学习的车型识别技术为实现高效准确的车辆分类和检测提供了强大的工具。本文将介绍如何利用深度学习技术来实现车型识别,并提供相应的代码示例。 数据收集和预处理: 为了训练…

前端TypeScript学习day01-TS介绍与TS部分常用类型

(创作不易,感谢有你,你的支持,就是我前行的最大动力,如果看完对你有帮助,请留下您的足迹) 目录 TypeScript 介绍 TypeScript 是什么 TypeScript 为什么要为 JS 添加类型支持? TypeScript 相…

gin路由相关方法

c.Request.URL.Path 拿到请求的路径 package mainimport ( "fmt" "github.com/gin-gonic/gin" "net/http")//路由重定向,请求转发,ANY ,NoRoute,路由组func main() { r : gin.Default() // -------…

notion + nextjs搭建博客

SaaS可以通过博客来获得SEO流量,之前我自己在nextjs上,基于MarkDown Cloudfare来构建博客,很快我就了解到更优雅的方案:notion nextjs搭建博客,之前搭建了过,没有记录,这次刚好又要弄&#xf…