防抖和节流的实现

news2024/11/18 23:27:47

防抖和节流的实现

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

什么是防抖和节流

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

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

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

防抖:在事件被触发 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.coloradmin.cn/o/1064974.html

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

相关文章

gin路由相关方法

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

Python 无废话-办公自动化Excel格式美化

设置字体 在使用openpyxl 处理excel 设置格式,需要导入Font类,设置Font初始化参数,常见参数如下: 关键字参数 数据类型 描述 name 字符串 字体名称,如Calibri或Times New Roman size 整型 大小点数 bold …

Spring注册Bean系列--方法5:@Import+ImportBeanDefinitionRegistrar

原文网址:Spring注册Bean系列--方法5:ImportImportBeanDefinitionRegistrar_IT利刃出鞘的博客-CSDN博客 简介 本文介绍Spring注册Bean的方法:ImportImportBeanDefinitionRegistrar。 注册Bean的方法我写了一个系列,见&#xff…

NAT模式和桥接模式的区别

NAT模式和桥接模式的区别 NAT模式和桥接模式都是虚拟机网络配置的两种方式,主要区别在于虚拟机与外部网络交互的方式不同。 NAT(Network Address Translation,网络地址转换)模式:在这种模式下,虚拟机和宿主…

SystemUI状态栏

SystemUI状态栏 1、日志开关2、相关属性配置3、Statusbar界面启动 android13-release 1、日志开关 Log.isLoggable通过设置属性,重启应用;Compile.IS_DEBUG日志开关是src-debug和src-release版本区别 frameworks\base\packages\SystemUI\src\com\android…

C++设计模式-外观(Facade)

目录 C设计模式-外观(Facade) 一、意图 二、适用性 三、结构 四、参与者 五、代码 C设计模式-外观(Facade) 一、意图 为子系统中的一组接口提供一个一致的界面,Facade模式定义了一个高层接口,这个接…

阿里云服务器Anolis OS龙蜥操作系统详细介绍

阿里云服务器Anolis OS镜像系统由龙蜥OpenAnolis社区推出,Anolis OS是CentOS 8 100%兼容替代版本,Anolis OS是完全开源、中立、开放的Linux发行版,具备企业级的稳定性、高性能、安全性和可靠性。目前阿里云服务器ECS可选的Anolis OS镜像系统版…

机器视觉行业最可怕的不是以量换价吗?而是买方市场的带量采购,量价挂钩

机器视觉行业其实有很多值得思考,人力成本(团队人数控制),硬件成本,售后成本,回款成本(收款成本)。那么我们今天谈谈带量采购,量价挂钩、以量换价。这个话题有很多争议,很多有趣的争论,也有值得我们后人评价。 什么是“以价换量”? 从经济学角度来看,“以价换量…

linux入门---信号的操作

目录标题 sigset_tsigset_t的操作函数sigprocmasksigpending信号的屏蔽测试sigaction sigset_t 为了能够让操作系统更好的使用信号,操作系统提供了sigset_t的数据类型,操作系统中存在pending表和block表,但是这两张表是内核数据结构&#xf…

数据结构-顺序存储二叉树

文章目录 目录 文章目录 前言 一 . 什么是顺序存储二叉树 二 . 模拟实现 前序遍历 总结 前言 大家好,今天给大家讲一下顺序存储二叉树 一 . 什么是顺序存储二叉树 顺序存储二叉树是一种将二叉树的节点按照从上到下、从左到右的顺序存储在数组中的方法。具体来说,顺…

Jackson 的 SNAKE_CASE 反序列化

最近项目中有关 JSON 的序列化和反序列化中,我们遇到了一个问题就是 category_id 我们在定义对象的时候使用的是 categoryId。 当程序进行反序列化的时候,我们获得的对象值为 NULL。 这是因为 jackson 提供了一个命名规则,如果你是希望进行…

FISCO BCOS(三十七)———FISCOBCOS应用开发,交易hash、区块高度的获取

这个需求怎么做? 交易hash的获取方式有很多,这里先介绍一种方式。 根据块高查询区块信息 https://webasedoc.readthedocs.io/zh_CN/latest/docs/WeBASE-Front/interface.html那我们如何知道现在的区块高度是多少? https://webasedoc.readthedocs.io/zh_CN/latest/docs/W…

谦卑篇(Be humble)//伟大是用卑微来换取的,任何时候都应该看清自己

1. 宇宙诞生138亿年,地球迄今经过了46亿个春秋,人生不过百年,//从生命科学的角度。 2. 蔡崇信:好的领导者是很谦卑的,他们会用谦卑雇佣来能力更强的人。// 从创业者的角度。 3. 《臣服实验》: 臣服生命之流…

新版Ai企业级系统去授权版本完美运行

Ai企联系统去授权版新鲜出炉 一款市面上新出的AI企联系统,一款市面上新出的AI企联系统 项目uniapp开发的,支持3.5 4.0 Mj 此套系统5端适配,WebH5微信小程序抖音小程序双端APP,支持流量主! 好像有能力的快手小程序那些也可以上…

高通camx开源部分学习简介

camera整体框架 sensor 上电,通过 MIPI协议传输,得到RAW图像数据。RAW图像数据经过ISP处理,得到YUV图像数据。YUV图像数据再经过DMA传输到DDR内存中,DDR内存也就是上图中标识的HOST。每个厂家的 ISP原理和功能大致相同&#xff0c…

Qt中 QMap 类、QHash 类、QVector 类详解

目录 一、QMap 类 1.插入数据信息 2.删除数据信息 3.迭代器 4.STL类型迭代 5.key键/T键查找 6.修改键值 7. 一个键对应多个值 直接使用QMultiMap类来实例化一个QMap对象 二、QHash 类 三、QVector类 一、QMap 类 QMap<Key,T>提供一个从类型为 Key 的键到类型为…

制作电商页面(Html)

任务 制作一个电商页面&#xff0c;要求所卖物品清晰&#xff0c;页面色调清晰&#xff0c;要有主页和详情页。 网站所买物品&#xff1a;书籍 色调&#xff1a;#FF2400 橙红色 代码 主页HTML代码&#xff1a; <html><head><meta charset"utf-8"…

力扣 -- 647. 回文子串

解题步骤&#xff1a; 参考代码&#xff1a; class Solution { public:int countSubstrings(string s) {int ns.size();vector<vector<bool>> dp(n,vector<bool>(n));//无需初始化int ret0;//一定要从下往上填写每一行for(int in-1;i>0;i--){//每一行的i…

Selenium基础

最近在学习爬虫的有关知识&#xff0c;发现一个很有意思的工具Selenium&#xff0c;所以打算花点时间看Selenium提供的手册来学习&#xff0c;为了防止以后忘记和方便复习&#xff0c;打算记录一下我的学习过程&#xff0c;我使用的Selenium版本是4.8.2。 目录 Selenium概述 网…

C++设计模式-享元(Flyweight)

目录 C设计模式-享元&#xff08;Flyweight&#xff09; 一、意图 二、适用性 三、结构 四、参与者 五、代码 C设计模式-享元&#xff08;Flyweight&#xff09; 一、意图 运用共享技术有效地支持大量细粒度的对象。 二、适用性 一个应用程序使用了大量的对象。完全由…