手写节流和防抖

一、什么是防抖

定义: 用于限制某个函数在短时间内被频繁调用的情况

特点:

  • 延迟执行:防抖会延迟执行目标函数,直到一定的空闲时间过去后才执行,如果在这段时间内再次触发,则会重新计时。

  • 合并触发:多次连续触发的事件会被合并为一次触发,只有在最后一次触发后的空闲时间内没有再次触发才会执行目标函数。

应用:

  • 输入框实时搜索:在用户输入搜索关键词时,使用防抖可以避免在用户输入过程中频繁触发搜索请求,提高搜索性能和用户体验。

  • 按钮点击事件:在防止用户重复点击按钮后多次触发事件时,可以利用防抖来控制按钮的点击事件,确保只有在用户停止点击后才执行操作。

  • 窗口大小调整:当用户调整窗口大小时,很多页面布局或响应式设计需要重新计算和调整,使用防抖可以确保在用户停止调整窗口大小后再执行相关操作,避免频繁重绘页面。

  • 滚动事件:处理页面滚动事件时,可以利用防抖减少滚动过程中触发的频繁计算,只有在用户滚动停止后才执行相关处理。

优点:

  • 性能优化:防抖可以减少不必要的函数执行次数,降低性能消耗,提高页面性能和响应速度。

  • 用户体验:在一些交互场景下,使用防抖可以有效控制事件触发频率,提升用户体验和界面流畅度。

  • 数据请求控制:在需要向后端发起请求的场景中,防抖可以避免频繁请求数据,减少网络流量和服务器压力。

总的来说,防抖是一种常用的前端技术,通过控制事件触发频率,可以优化性能、提升用户体验,并有效应用于多种交互场景中。

案例:
逻辑梳理:

  • 在这个示例中,debounce函数接受两个参数:需要防抖的函数 func 和延迟时间 delay。返回一个新的函数,用于包裹原始函数 func,并在延迟时间内只允许触发一次执行。

  • 通过调用 debounce(doSomething, 1000) 创建一个防抖函数 debouncedFunction,然后可以多次调用 debouncedFunction,但实际执行的是 doSomething 函数,并且在延迟时间内多次调用会重新计时,只有在延迟时间后才会执行 doSomething 函数。

  • 这样可以确保在需要控制某个函数执行频率的场景下,防抖函数可以帮助避免频繁触发,提升性能和用户体验。

// 防抖函数
function debounce(func, delay) {let timeoutId;return function() {const context = this;const args = arguments;clearTimeout(timeoutId);timeoutId = setTimeout(() => {func.apply(context, args);}, delay);};
}// 示例:模拟一个需要防抖的函数
function doSomething() {console.log('Doing something important!');
}// 创建防抖函数
const debouncedFunction = debounce(doSomething, 1000); // 设置延迟时间为1000毫秒// 调用防抖函数
debouncedFunction(); // 第一次调用
debouncedFunction(); // 在1000毫秒内再次调用
debouncedFunction(); // 在1000毫秒内再次调用

二、什么是节流

定义: 与防抖类似,用于控制某个函数在短时间内被频繁调用的情况
特点:

  • 控制执行频率:节流会确保目标函数在一定时间间隔内只执行一次,即使触发事件多次也不会立即执行,而是在规定的时间间隔后执行。

  • 固定时间间隔:与防抖不同,节流在规定的时间间隔内始终按照固定频率执行函数,不会重新计时。

应用:

  • 页面滚动事件:在处理页面滚动事件时,通过节流可以限制触发频率,比如实现图片懒加载或滚动加载数据。

  • 窗口调整事件:当用户调整窗口大小时,使用节流可以确保在一定时间间隔内执行相关布局调整或响应式设计操作。

  • 按钮点击事件:类似于防抖,节流也可用于控制按钮点击事件的触发频率,确保在一定时间间隔内只执行一次。

  • 用户输入事件:在需要实时反馈用户输入内容的场景中,通过节流可以控制输入事件的处理频率,避免频繁更新UI。

优点:

  • 性能优化:节流可以有效减少函数执行次数,降低性能开销,提高页面性能和响应速度。

  • 流畅交互:通过控制事件执行频率,节流可以确保用户交互过程更加流畅,避免过多的重复操作。

  • 数据请求控制:在需要向服务器请求数据的场景中,节流可以限制请求频率,减少不必要的数据请求,节省网络流量和服务器资源。

总的来说,节流是一种常用的前端技术,通过控制函数执行频率,可以优化性能、提升用户体验,并广泛应用于各种交互场景中。

案例:
逻辑梳理:

  • 在这个示例中,throttle函数接受两个参数:需要节流的函数 func 和间隔时间 delay。返回一个新的函数,用于包裹原始函数 func,并在间隔时间内限制函数的执行频率。

  • 通过调用 throttle(doSomething, 1000) 创建一个节流函数 throttledFunction,然后可以多次调用 throttledFunction,但实际执行的是 doSomething 函数,并且保证在间隔时间内只执行一次。

  • 这样可以确保在需要控制某个函数执行频率的场景下,节流函数可以帮助限制函数的执行频率,避免过多的函数调用,提升性能和用户体验。

// 节流函数
function throttle(func, delay) {let lastCall = 0;return function() {const now = new Date().getTime();if (now - lastCall >= delay) {func();lastCall = now;}};
}// 示例:模拟一个需要节流的函数
function doSomething() {console.log('Doing something important!');
}// 创建节流函数
const throttledFunction = throttle(doSomething, 1000); // 设置间隔时间为1000毫秒// 模拟连续调用节流函数
throttledFunction(); // 第一次调用
throttledFunction(); // 在1000毫秒内再次调用,不会执行
setTimeout(throttledFunction, 500); // 在500毫秒后调用,不会执行
setTimeout(throttledFunction, 1500); // 在1500毫秒后调用,会执行

防抖和节流

function debounce(func, wait, opts = {}) {let maxWait;if ('maxWait' in opts) {maxWait = opts.maxWait;}let leading = true; // 是否在第一次触发时立即执行let trailing = true; // 是否在最后一次触发后执行let lastCallTime; // 上次调用函数的时间let timeout; // 定时器let lastThis; // 函数执行时的 thislet lastArgs; // 函数执行时的参数let lastInvokeTime; // 上次函数实际被调用的时间// 判断是否应该调用函数let shouldInvoke = function (now) {let sinceLastTime = now - lastCallTime;let sinceLastInvoke = now - lastInvokeTime;return lastCallTime === undefined || sinceLastTime > wait || sinceLastInvoke >= maxWait;}// 执行函数let invokeFunc = function (time) {lastInvokeTime = time; // 记录函数实际被调用的时间func.apply(lastThis, lastArgs); // 执行函数}// 启动定时器let startTimer = function (timerExpired, wait) {timeout = setTimeout(timerExpired, wait);}// 计算剩余等待时间let remainingWait = function (now) {return wait - (now - lastCallTime);}// 最后一次触发后执行函数let trailingEdge = function (time) {timeout = undefined;if (trailing) {invokeFunc(time);}}// 定时器到期后的处理逻辑let timerExpired = function () {let now = Date.now();if (shouldInvoke(now)) {return trailingEdge(now);}startTimer(timerExpired, remainingWait(now));}// 第一次触发时执行函数let leadingEdge = function (time) {lastInvokeTime = time;if (leading) {invokeFunc(time);}startTimer(timerExpired, wait); // 开启定时器,准备执行下一次函数调用}// 返回一个处理防抖逻辑的函数let debounced = function (...args) {lastThis = this;lastArgs = args;let now = Date.now();let isInvoking = shouldInvoke(now);lastCallTime = now;if (isInvoking) {if (timeout === undefined) {leadingEdge(now);}}}return debounced;
}

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

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

相关文章

WHAT - 常见的前端工具库

前端开发有许多工具库,可以帮助开发者提高效率、简化代码和增强功能。以下是一些常见的前端工具库: 一、常见工具库 函数库 1. Lodash(推荐) Lodash 是一个 JavaScript 实用程序库,提供了一系列方便的函数&#xf…

鹤城杯 2021 流量分析

看分组也知道考http流量 是布尔盲注 过滤器筛选http流量 将流量包过滤分离 http tshark -r timu.pcapng -Y "http" -T json > 1.json这个时候取 http.request.uri 进一步分离 http.request.uri字段是我们需要的数据 tshark -r timu.pcapng -Y "http&quo…

【全开源】Java情侣飞行棋系统微信小程序+H5+APP源码+微信公众号

​让爱情与游戏并行 一、引言:飞行棋与情侣时光的交融 在快节奏的现代生活中,情侣们常常寻找一种既能增进感情又能共同娱乐的方式。飞行棋,这款经典的家庭游戏,因其简单易上手、策略性强而深受大众喜爱。而现在,我们…

Vue2中的计算属性(computed)和监听属性(watch)

1、说明 在Vue中我们经常会使用到多个参数计算出来的结果,在这种情况下我们可以定义参数和方法,将处理结果赋值给自定义参数,这种方式较为复杂,由此vue提供了计算属性方法。面对响应式页面,我们为了做到实时响应页面参…

[个人笔记] 记录docker-compose的部署过程

容器技术 第二章 记录docker-compose的部署过程 容器技术记录docker-compose的部署过程(可选)新建docker用户(可选)迁移docker-ce目录docker-compose官方插件形式安装官方二进制形式独立安装(可选) 使用docker-compose二进制包的 bash_completion 命令补齐 参考来源 记录docker…

Android8.1高通平台修改默认输入法

需求 安卓8.1 SDK原生的输入法只能打英文, 需要替换成中文输入法. 以高通平台为例, 其它平台也适用. 查看设备当前默认输入法 adb shell settings list secure | grep input 可以看到当前默认是LatinIME这个安卓原生输入法. default_input_methodcom.android.inputmethod.l…

使用compile_commands.json配置includePath环境,解决vscode中引入头文件处有波浪线的问题

通过编译时生成的 compile_commands.json 文件自动完成对 vscode 中头文件路径的配置,实现 vscode 中的代码的自动跳转。完成头文件路径配置后,可以避免代码头部导入头文件部分出现波浪线,警告说无法正确找到头文件。 步骤 需要在 vscode 中…

木馒头头戴式蓝牙耳机

这里写目录标题 木馒头二代头戴式蓝牙耳机清除连接记忆 木馒头二代头戴式蓝牙耳机清除连接记忆 在配对模式下,同时按住播放和暂停按钮4秒,LED闪烁紫色3次,即为清除成功。

电子烟开发【恒压、恒有效算法】

恒压算法 pwm是通过软件模拟的 pwm满值运行是250全占空比 #define D_TARGET_AVERAGE_VOLTAGE 3500 //R_ADC1_Vout :发热丝两端AD值 //R_ADC_FVR :电池电压AD值 //FVR_VOLTAGE :电池AD参考电压 满电值AD //R_Smk1Duty :最后…

Java 面试题:String、StringBuffer、StringBuilder 有什么区别?

几乎所有的应用开发都离不开操作字符串,理解字符串的设计和实现以及相关工具如拼接类的使用,对写出高质量代码是非常有帮助的。关于这个问题,我前面的回答是一个通常的概要性回答,至少你要知道 String 是 Immutable 的&#xff0c…

深入分析 Android Service (一)

文章目录 深入分析 Android Service (一)1. Android Service 设计说明1.1. Service 的类型1.2. Service 的生命周期1.3. 创建和启动 Service1.4. 绑定 Service1.5. ServiceConnection1.6. 前台 Service1.7. IntentService示例:创建和使用 IntentService 2. Service …

CentOS7部署Yearning并配置MySQL数据库远程访问详细流程——“cpolar内网穿透”

文章目录 前言1. Linux 部署Yearning2. 本地访问Yearning3. Linux 安装cpolar4. 配置Yearning公网访问地址5. 公网远程访问Yearning管理界面6. 固定Yearning公网地址 前言 本文主要介绍在 Linux 系统简单部署 Yearning 并结合 cpolar 内网穿透工具实现远程访问,破除…

Git基本使用教程(学习记录)

参考文章链接: Git教程(超详细,一文秒懂) RUNOOB Git教程 Git学习记录 1Git概述 1.1版本控制软件功能 版本管理:更新或回退到历史上任何版本,数据备份共享代码:团队间共享代码,…

立哥开源技术-基于Python的TTS分析脚本

import pyttsx3 # 创建一个引擎实例 engine pyttsx3.init() # 获取所有可用的语音列表 voices engine.getProperty(voices) # 打印出所有可用的语音名称和属性 for voice in voices: print("Voice:") print(" - 名称: %s" % voice.name) …

【vscode篇】1-VScode设置语言为中文,2-解决中文注释乱码问题。

设置语言为中文 在前端开发中,Visual Studio Code(简称vscode)是一个非常好用的工具,但第一次打开vscode会发现界面为英文,这对很多开发者来说会很不友好(比如我),把界面设置成中文只需要安装一个插件即可&…

从零入门激光SLAM(二十二)——Fast-lio2代码详解(三) 迭代误差更新

Fast-lio2原理解析见链接从零入门激光SLAM(二十一)——看不懂FAST-LIO?进来_fastlio 雷达 更改频率-CSDN博客 注释版代码完整版见GitHub - huashu996/Fast-lio2-Supernote: Fast-lio2 code with note 本代码解析以算法流程的逻辑解析代码&…

C#面:如果不用VisualStudio,用哪个命令行编译C#程序

可以使用命令提示符或者终端来执行编译命令 csc.exe 。 步骤: 打开命令提示符或终端。使用 cd 切换到 C# 程序所在的目录。使用以下命令来编译C#程序: 其中,是你的C#源代码文件的名称(包括扩展名.cs)。如果编译成功&…

ONLYOFFICE 协作空间与 WordPress 如何集成

转载自作者:VincentYoung,略有改动 阅读本文,了解如何将 ONLYOFFICE 协作空间与 WordPress 进行集成。 ONLYOFFICE 协作空间是其去年新推出的产品,用创建虚拟办公室房间的方式,来组织公司内部团队成员的在线协作办公&…

C++中的双指针和三指针

目录 摘要 双指针(Double Pointers) 含义 使用场景 三指针(Triple Pointers) 含义 使用场景 总结 双指针的详细说明 三指针的详细说明 摘要 在C中,双指针和三指针分别是指向指针的指针和指向指向指针的指针…

C. Swap Adjacent Elements 题解

C. Swap Adjacent Elements 题解 S A E 题目大意思路代码题目大意 输入格式: 第一行一个整数 n n n ( 2 ≤ (2≤ (2≤ n n n ≤ 200000 ) ≤200000) ≤200000) 第二行 n个整数 a 1 a_1 a1​, a 2 a_2 a2​