【JS进阶】防抖与节流
防抖与节流
1.防抖
1.1 为什么要防抖?
在项目中,有的操作是高频触发的,但是其实触发一次就好了,比如我们短时间内多次缩放页面,那么我们不应该每次缩放都去执行操作,应该只做一次就好。再比如说监听输入框的输入,不应该每次都去触发监听,应该是用户完成一段输入后再进行触发。
所以,防抖就是防止抖动,避免事件的重复触发。
思路:等待用户高频操作完成后,再完成操作。
1.2 基础防抖如何实现?

基础设计思路:事件触发后,开启一个定时器,当该定时器到时间时,触发操作;而如果事件在该定时器限定的时间内再次触发,则清除当前定时器,并再次开启一个新的定时器。
代码如下:
// fn --- 要执行的操作,delay --- 延迟时间,在该时间内用户没有再次触发则执行操作
function debounce(fn, delay){// timer --- 定时器的名称,用于清除定时器let timer = null;return function(arguments){// 实际进行防抖的部分// 如果再次触发,首先清除上一次的定时器clearTimeout(timer);// 创建一个新定时器并记录名称timer = setTimeout(()=> {// 用apply方法执行目标函数fn.apply(this, arguments);}, delay)}
}
实际上,可以通过下面这张图来理解基础的防抖:

2.节流
2.1 为什么要节流?
基础的防抖存在一个问题,事件会一直等到用户完成操作后一段时间在操作,如果一直操作,会一直不触发。比如说是一个按钮,点击就发送请求,如果一直点,那么请求就会一直发布出去。这里正确的思路应该是第一次点击就发送,然后上一个请求回来后,才能再发,即节流。
节流就是减少流量,将频繁触发的事件减少,并每隔一段时间执行。即,控制事件触发的频率。
思路:某个操作希望上一次的完成后再进行下一次,或者希望隔一段时间触发一次
2.2 如何实现基础节流?

基础设计思路:我们可以设计一种类似控制阀门一样定期开放的函数,事件触发时让函数执行一次,然后关闭这个阀门,过了一段时间后再将这个阀门打开,再次触发事件。
代码如下:
// fn --- 要执行的操作,delay --- 延迟时间,在该时间内操作最多只会执行一次
function throttle(fn, delay){// 阀门是否开启let valid = true;return function(arguments){if(valid) { //如果阀门已经打开,就继续往下,设定定时器,指明在一定延迟时间后执行一次操作// 此时已经确定会执行一次操作,因此关闭阀门valid = false;setTimeout(()=> {fn.apply(this, arguments);//定时器结束后执行valid = true;//执行完成后打开阀门}, delay)}}
}
实际上,可以通过下面这张图来理解基础的节流:

3.防抖节流的应用场景、联系以及区别
防抖
- search搜索联想,用户在不断输入值时,用防抖来节约请求资源
- window触发resize的时候,不断的调整浏览器窗口大小会不断的触发这个事件,用防抖来让其只触发一次
节流
- 鼠标不断点击触发,mousedown(单位时间内只触发一次)
- 监听滚动事件,比如是否滑到底部自动加载更多
联系与区别
防抖节流的共同点在于:都是为了阻止操作高频触发,从而浪费性能。
两者的不同点在于:
- 防抖是触发高频事件后n秒内函数只会执行一次,如果n秒内高频事件再次被触发,则重新计时。适用于可以多次触发但触发只生效最后一次的场景,可能会出现操作始终不执行的情况。
- 而节流则不同,事件高频触发,无论触发多少次,在一定时间内只会执行一次,即定期执行。相比于防抖,节流的响应更加平滑,不会出现始终不执行操作的情况!
4.防抖与节流的优化
对于上面的基础防抖与节流的方法,主要有两个可以优化的方面:
- 复用性优化:对于实际项目中,我们不可能在每次需要进行防抖节流的时候,都重新写一遍代码,因此,我们需要将防抖节流的方法封装为内部API提高复用性!
- 功能方面的优化:
- 防抖:添加立即执行选项解决可能始终不执行的问题;延迟防抖,解决高频设定定时器的问题。
- 节流:可能需要点击后立即执行等等。
立即执行
在某些业务场景中,使用防抖节流时,基础的防抖节流可能会导致响应时间变长,这就会影响到用户的使用体验,因此,需要在触发事件的时候,立即执行处理函数,但后续也能起到防抖节流的作用。
立即执行的防抖和节流,其原理是一致的,即:添加一个计数器或立即执行的标识。
实现如下:
// 防抖
export const debounce = (fun , wait=1000) => {let timeout = nulllet count = 0return function(){let _this = thislet arg = argumentsif(timeout){//如果存在定时器就清空clearTimeout(timeout)}if (!count) {// 第一次点击时立即执行count++fun.apply(_this, arg)timeout = setTimeout(() => {count = 0}, wait)} else {count++timeout = setTimeout(() => {fun.apply(_this, arg)count = 0}, wait)}}
}// 节流
export const throttled = (fun, wait=1000, immediate) => {let preTime = 0;let timerId;return function() {let _this = this;let args = arguments;if(immediate) { // immediate 为true 时立即执行let nowTime = Date.now();if(nowTime - preTime > wait) {fun.apply(_this, args);preTime = nowTime;}} else {if(!timerId) {timerId = setTimeout(function() {fun.apply(_this, args);timerId = null;}, wait);}}}
}
其他优化
在不同的业务场景中,对于防抖节流也有不同的需求,如果单纯地为了每一个场景编写防抖节流函数,是相当费事且麻烦的工作,因此,不如使用别人封装好的库。
参考:http://t.csdn.cn/RVzMK
最终解决方案:
underscore.js 库中的 _.throttle() 和 _.debounce() — 参考https://www.likecs.com/show-307738657.html
相关文章:
【JS进阶】防抖与节流
防抖与节流 1.防抖 1.1 为什么要防抖? 在项目中,有的操作是高频触发的,但是其实触发一次就好了,比如我们短时间内多次缩放页面,那么我们不应该每次缩放都去执行操作,应该只做一次就好。再比如说监听输入…...
【css】linear-gradient()的用法
linear-gradient() CSS函数创建一个由两种或多种颜色沿一条直线进行线性过渡的图像,其结果是<gradient>数据类型的对象,此对象是一种特殊的<image> 数据类型。 语法 /* 渐变轴为 45 度,从蓝色渐变到红色 */ linear-gradient(45deg, blue, red);/* 从右…...
java: 读取snakeyaml-1.26.jar各种jar包时出错; error in opening zip file
可能的问题 jar有问题idea没有权限等等其他问题。但执行后报错就是读取不了,还报error in opening zip file这个错。 解决问题 我的错就是jar包有问题。我先后进行了很多次把jar包位置里的东西全部删除,然后重新maven下载但是不管用。最后从网站上下载…...
医疗知识图谱 neo4j
开源项目: https://github.com/liuhuanyong/QASystemOnMedicalKG 一.效果 二.需要安装: pip install pyahocorasick pip install py2neo 三.需要修改: 需要改的点: 1.改连接的方式 2.改读文件的方式 MedicalGraph 运行&am…...
【LeetCode-简单题】367. 有效的完全平方数
文章目录 题目方法一:二分查找 题目 方法一:二分查找 找 1 - num 之间的 mid, 开方是整数 就找得到 mid, 不是整数自然找不到mid class Solution { // 二分查找 ;找 1 - num 之间的mid 开方是整数 就找得到 不是…...
vben-admin中渲染table表格时怎么处理不同的数据结构
最近在用vben admin开发后台管理系统,vben admin这个后管端框架封装的非常细,颗粒度非常细,如果了解里面的组件或者api用法,那开发起来非常快。如果不了解,那就非常痛苦了,目前关于vben admin这块的开发问题…...
从零开始在树莓派上搭建WordPress博客网站并实现公网访问
文章目录 序幕概述1. 安装 PHP2. 安装MySQL数据库3. 安装 Wordpress4. 设置您的 WordPress 数据库设置 MySQL/MariaDB创建 WordPress 数据库 5. WordPress configuration6. 将WordPress站点发布到公网安装相对URL插件修改config.php配置 7. 支持好友链接样式8. 定制主题 序幕 …...
Go基础18-理解方法的本质以选择正确的receiver类型
Go语言虽然不支持经典的面向对象语法元素,比如类、对象、继承等,但Go语言也有方法。和函数相比,Go语言中的方法在声明形式上仅仅多了一个参数,Go称之为receiver参数。receiver参数是方法与类型之间的纽带。 Go方法的一般声明形式…...
Go基础12-理解Go语言表达式的求值顺序
Go语言在变量声明、初始化以及赋值语句上相比其先祖C语言做了一些改进,诸如: ● 支持在同一行声明和初始化多个变量(不同类型也可以) var a, b, c 5, "hello", 3.45 a, b, c : 5, "hello", 3.45 // 短变量…...
OJ练习第165题——修车的最少时间
修车的最少时间 力扣链接:2594. 修车的最少时间 题目描述 给你一个整数数组 ranks ,表示一些机械工的 能力值 。ranksi 是第 i 位机械工的能力值。能力值为 r 的机械工可以在 r * n2 分钟内修好 n 辆车。 同时给你一个整数 cars ,表示总…...
纯前端实现 导入 与 导出 Excel
最近经常在做 不规则Excel的导入,或者一些普通Excel的导出,当前以上说的都是纯前端来实现;下面我们来聊聊经常用到的Excel导出与导入的实现方案,本文实现技术栈以 Vue2 JS 为例 导入分类: 调用 API 完全由后端来解析数…...
关于一次两段式提交和数据库恢复数据我的一些想法
binlog是服务层的功能,而redolog是innodb引擎的功能,binlog主要用于主从复制,redolog主要用做数据的恢复,我们必须保证binlog和redolog日志数据的一致性。恢复数据时也必须遵守此一致性。 1.如果只写一次redolog会出现什么问题&a…...
阿里巴巴springcloud的gateway网关如何用继承接口WebExceptionHandler定义一个json格式的404错误页面实例
如果你想通过实现 WebExceptionHandler 接口来定义一个返回 JSON 格式的 404 错误页面的实例,可以按照以下方式操作: import org.springframework.core.annotation.Order; import org.springframework.http.HttpStatus; import org.springframework.ster…...
『力扣每日一题07』字符串最后一个单词的长度
气死我啦,今天这道题花了快一个小时,我学完了答案的解法,放上去在线 OJ ,一直报错,找来找去都找不到自己错在哪,明明跟答案一模一样。后来还是学了另一种解法,才跑出来的(̥̥̥̥̥̥̥̥o̥̥…...
成都睿趣科技:抖音开店初期要注意什么
随着社交媒体和短视频平台的崛起,抖音已经成为了一个风靡全球的短视频应用,拥有着庞大的用户群体。因此,越来越多的创业者开始在抖音上开设自己的线上店铺,希望借助这个平台赚取丰厚的利润。然而,在抖音开店初期&#…...
QT 5.13保姆级安装教程
辨清关系 要想学习一个新的东西,我们必须知其事,达其理,悟其道,然后才能无往而不利也! 我们常听到QT、Qt Creator 和 Qt SDK ,这三者究竟是什么,他们之间的关系又是如何的?在安装QT之前我们先来了解一下他们之间的关系: Qt:Qt 是一个跨平台的 C++ 应用程序开发框架,…...
js 创建DOM,并添加父DOM上,移除某个DOM的所有子节点
在sectionIdDiv上,添加子DOM <div ref"sectionIdDiv" class"sectionIdDiv"> </div>创建你要添加的子DOM ## 创建DOM let elementDom document.createElement(div)## 设置DOM的样式 elementDom.style.height "15px" e…...
element el-input 二次封装
说明:为实现输入限制,不可输入空格,长度限制。 inputView.vue <template><!-- 输入框 --><el-input:type"type":placeholder"placeholder"v-model"input"input"inputChange":maxle…...
[源码系列:手写spring] IOC第十三节:Bean作用域,增加prototype的支持
为了帮助大家更深入的理解bean的作用域,特意将BeanDefinition的双例支持留到本章节中,创建Bean,相关Reader读取等逻辑都有所改动。 内容介绍 在Spring中,Bean的作用域(Scope)定义了Bean的生命周期和可见性。包括单例和…...
【性能优化】事件委托
一、为什么要用事件委托 当 dom 有事件处理程序时,我们一般都会直接给它设置事件处理程序,设想一下,如果在一个父元素中有很多个 dom 需要添加事件处理呢?比如 ul 中处在100个 li,每个 li 都有相同的 click 事件&…...
Python:操作 Excel 折叠
💖亲爱的技术爱好者们,热烈欢迎来到 Kant2048 的博客!我是 Thomas Kant,很开心能在CSDN上与你们相遇~💖 本博客的精华专栏: 【自动化测试】 【测试经验】 【人工智能】 【Python】 Python 操作 Excel 系列 读取单元格数据按行写入设置行高和列宽自动调整行高和列宽水平…...
LINUX 69 FTP 客服管理系统 man 5 /etc/vsftpd/vsftpd.conf
FTP 客服管理系统 实现kefu123登录,不允许匿名访问,kefu只能访问/data/kefu目录,不能查看其他目录 创建账号密码 useradd kefu echo 123|passwd -stdin kefu [rootcode caozx26420]# echo 123|passwd --stdin kefu 更改用户 kefu 的密码…...
Kubernetes 网络模型深度解析:Pod IP 与 Service 的负载均衡机制,Service到底是什么?
Pod IP 的本质与特性 Pod IP 的定位 纯端点地址:Pod IP 是分配给 Pod 网络命名空间的真实 IP 地址(如 10.244.1.2)无特殊名称:在 Kubernetes 中,它通常被称为 “Pod IP” 或 “容器 IP”生命周期:与 Pod …...
Cilium动手实验室: 精通之旅---13.Cilium LoadBalancer IPAM and L2 Service Announcement
Cilium动手实验室: 精通之旅---13.Cilium LoadBalancer IPAM and L2 Service Announcement 1. LAB环境2. L2公告策略2.1 部署Death Star2.2 访问服务2.3 部署L2公告策略2.4 服务宣告 3. 可视化 ARP 流量3.1 部署新服务3.2 准备可视化3.3 再次请求 4. 自动IPAM4.1 IPAM Pool4.2 …...
【Post-process】【VBA】ETABS VBA FrameObj.GetNameList and write to EXCEL
ETABS API实战:导出框架元素数据到Excel 在结构工程师的日常工作中,经常需要从ETABS模型中提取框架元素信息进行后续分析。手动复制粘贴不仅耗时,还容易出错。今天我们来用简单的VBA代码实现自动化导出。 🎯 我们要实现什么? 一键点击,就能将ETABS中所有框架元素的基…...
ArcPy扩展模块的使用(3)
管理工程项目 arcpy.mp模块允许用户管理布局、地图、报表、文件夹连接、视图等工程项目。例如,可以更新、修复或替换图层数据源,修改图层的符号系统,甚至自动在线执行共享要托管在组织中的工程项。 以下代码展示了如何更新图层的数据源&…...
数据结构:泰勒展开式:霍纳法则(Horner‘s Rule)
目录 🔍 若用递归计算每一项,会发生什么? Horners Rule(霍纳法则) 第一步:我们从最原始的泰勒公式出发 第二步:从形式上重新观察展开式 🌟 第三步:引出霍纳法则&…...
拟合问题处理
在机器学习中,核心任务通常围绕模型训练和性能提升展开,但你提到的 “优化训练数据解决过拟合” 和 “提升泛化性能解决欠拟合” 需要结合更准确的概念进行梳理。以下是对机器学习核心任务的系统复习和修正: 一、机器学习的核心任务框架 机…...
qt+vs Generated File下的moc_和ui_文件丢失导致 error LNK2001
qt 5.9.7 vs2013 qt add-in 2.3.2 起因是添加一个新的控件类,直接把源文件拖进VS的项目里,然后VS卡住十秒,然后编译就报一堆 error LNK2001 一看项目的Generated Files下的moc_和ui_文件丢失了一部分,导致编译的时候找不到了。因…...
6.计算机网络核心知识点精要手册
计算机网络核心知识点精要手册 1.协议基础篇 网络协议三要素 语法:数据与控制信息的结构或格式,如同语言中的语法规则语义:控制信息的具体含义和响应方式,规定通信双方"说什么"同步:事件执行的顺序与时序…...
