当前位置:网站首页>JS封装防抖(代码持续优化)
JS封装防抖(代码持续优化)
2022-08-09 11:25:00 【ik i5】
1 .认识防抖debounce函数
- 防抖的过程
- 当事件触发时,相应的函数并不会立即触发,而是会等待一定的时间;
- 当事件密集触发时,函数的触发会被频繁的推迟;
- 只有等待了一段时间也没有事件触发,才会真正的执行响应函数;

- 防抖的应用场景
- 输入框中频繁的输入内容,搜索或 者提交信息;
- 频繁的点击按钮,触发某个事件;
- 监听浏览器滚动事件,完成某些特定操作;
- 用户缩放浏览器的resize事件;
2. 防抖函数的案例
我们都遇到过这样的场景,在某个搜索框中输入自己想要搜索的内容:
- 比如想要搜索一个MacBook:
- 当我输入m时,为了更好的用户体验,通常会出现对应的联想内容,这些联想内容通常是保存在服务器的,所以需要一次网络请求;
- 当继续输入ma时,再次发送网络请求;
- 那么macbook一共需要发送7次网络请求;
- 这大大损耗我们整个系统的性能,无论是前端的事件处理,还是对于服务器的压力;
- 但是我们需要这么多次的网络请求吗?
- 不需要,正确的做法应该是在合适的情况下再发送网络请求;
- 比如如果用户快速的输入一个macbook,那么只是发送一次网络请求;
- 比如如果用户是输入一个m想了一会儿,这个时候m确实应该发送一次网络请求;
- 也就是我们应该监听用户在某个时间,比如500ms内,没有再次触发时间时,再发送网络请求;
这就是防抖的操作:只有在某个时间内,没有再次触发某个函数时,才真正的调用这个函数;
游戏理解: 防抖就回城
生活理解: 坐电梯

3.利用 第三方库来实现防抖
<!-- //第三方库使用防抖节流 -->
<input type="text">
<script src="https://cdn.jsdelivr.net/npm/[email protected]/underscore-umd-min.js"></script>
<script>
const inputEl = document.querySelector('input')
let count = 0
const inputChange = function (event) {
count++
console.log(`发送了我们的第${
count}次网络请求`, this,event);
}
// 防抖只执行一次
inputEl.oninput=_.debounce(inputChange,2000)
4. 手写防抖
4. 1防抖基本功能的实现
<!-- //第三方库使用防抖节流 -->
<input type="text">
<!-- <script src="https://cdn.jsdelivr.net/npm/[email protected]/underscore-umd-min.js"></script> -->
<script>
const inputEl = document.querySelector('input')
let count = 0
const inputChange = function () {
count++
console.log(`发送了我们的第${
count}次网络请求`);
}
// 防抖只执行一次
inputEl.oninput = debounce(inputChange, 2000)
// 1 防抖的过程需要传递两个值一个是函数fn另一个是时间
function debounce(fn, times) {
// 定义一个定时器来来记录上一次的定时器函数的状态
let timer = null
// 2 在接受这两个值时需要返回一个函数
const _debounce = function () {
// 3 在处理防抖时 需要只执行一次 这里需要一个计时器
// 4 计时器有一个返回的id属性值 ,利用返回的id,让函数只执行最后一次
// 5 如果有这个id 则停止计时器
if (timer) clearInterval(timer) //取消上一次定时器
timer = setTimeout(() => {
//延迟执行
fn() //外部传入的函数
}, times)
}
return _debounce
}
</script>
优化
// 防抖的关键在于定时器的开始与清零
function debounce(callback,delaytime){
// 定义计时器
let timer=null
return function(){
//如果定时器不是null 则需要重新计时
if (timer!=null) {
clearTimeout(timer)
}
//如果定时器还是空 ,则开始倒计时
timer=setTimeout(()=>{
callback&&callback()
}, delaytime)
}
}
4. 2优化参数和this指向
注意上面的this指向为window 参数传递为undefined
<input type="text">
<!-- <script src="https://cdn.jsdelivr.net/npm/[email protected]/underscore-umd-min.js"></script> -->
<script>
const inputEl = document.querySelector('input')
let count = 0
const inputChange = function (event) {
count++
console.log(`发送了我们的第${
count}次网络请求`, this,event); //这里的this指向window ,event传递的参数指向undefined
//因此需要重新绑定this
}
// 防抖只执行一次
inputEl.oninput = debounce(inputChange, 2000)
// 1 防抖的过程需要传递两个值一个是函数fn另一个是时间
function debounce(fn, times) {
// 定义一个定时器来来记录上一次的定时器函数的状态
let timer = null
// 2 在接受这两个值时需要返回一个函数 (真正需要执行的函数)
const _debounce = function (...args) {
//这里处理args传递的参数
// 3 在处理防抖时 需要只执行一次 这里需要一个计时器
// 4 计时器有一个返回的id属性值 ,利用返回的id,让函数只执行最后一次
// 5 如果有这个id 则取消上一次计时器
if (timer) clearInterval(timer) //取消上一次定时器
timer = setTimeout(() => {
//延迟执行
fn.apply(this,args) //外部传入的函数
//在这里重新绑定this(不绑定this指向的是windows =>这里改变this重新指向调用者input)
}, times)
}
return _debounce
// 问题: 主函数需要先执行 ,只不过返回的是undefined
//undefined 游览器自己处理不做判断
}
</script>
4. 3 优化立即执行效果(第一次立即执行)
<!-- 题注 当用户输入一次时, 先执行一次 =>产生联想 -->
<!-- //第三方库使用防抖节流 -->
<input type="text">
<script>
const inputEl = document.querySelector('input')
let count = 0
const inputChange = function (event) {
count++
console.log(`发送了我们的第${
count}次网络请求`, this, event); //这里的this指向window ,event传递的参数指向undefined
//因此需要重新绑定this
}
// 防抖只执行一次
inputEl.oninput = debounce(inputChange, 2000,true) //这里可以传入第三个参数
// 1 防抖的过程需要传递两个值一个是函数fn另一个是时间
function debounce(fn, times, imediate=false) {
//immediate是否立即执行,默认情况下是不需要立即执行的传入false
let timer = null
// 定义全局判断上一次是否是立即执行
let isVoke=false
const _debounce = function (...args) {
if (timer) clearInterval(timer) //取消上一次定时器
//判断是否需要立即执行
if (imediate &&!isVoke) {
//!isVoke=true
fn.apply(this,args)
// imediate=false //立即执行完成之后改成false 分析问题 当下一次重新输入时 不会立即执行=>延迟执行
isVoke=true //这里赋值为true 当上一次执行完毕后赋值为true //让其延迟执行
}else{
//延迟执行
timer = setTimeout(() => {
//延迟执行
fn.apply(this, args) //外部传入的函数
isVoke=false //abcd=> 当abcd执行完后重启false 在判断是否立即执行
}, times)
}
}
return _debounce
}
- 后期优化返回值 , 以及取消功能
边栏推荐
- PAT1012
- 【VIBE: Video Inference for Human Body Pose and Shape Estimation】论文阅读
- 七夕?程序员不存在的~
- This application has no explicit mapping for /error, so you are seeing this as a fallback
- 【VQA survey】视觉问答中的语言学问题
- Qt获取EXE可执行文件的上一级目录下的文件
- [现代控制理论]6_稳定性_李雅普诺夫_Lyapunov
- SQL Server查询优化
- ICML 2022 | Out-of-Distribution检测与深最近的邻居
- Qt读写.ini配置文件
猜你喜欢

x86异常处理与中断机制(2)中断向量表

Chinese valentine's day?Programmers don't exist

Qt读写.ini配置文件

enum in c language

【Subpixel Dense Refinement Network for Skeletonization】CVPR2020论文解读

End-to-End Object Detection with Fully Convolutional Network学习笔记

MDK添加注释模板

BISS绝对值编码器_TI方案_线路延迟补偿

无刷无霍尔BLCD电机控制

Visual Studio 2017 ASP.NET Framework MVC 项目 MySQL 配置连接
随机推荐
ACM最长不下降子序列问题
CentOS6.5 32bit安装Oracle、ArcSde、Apache等配置说明
PTA习题 三角形判断
wait system call
The use of C language typedef 】 : structure, basic data types, and array
2022 全球 AI 模型周报
C语言中信号函数(signal)的使用
Visual Studio 2017 ASP.NET Framework MVC 项目 MySQL 配置连接
激光条纹中心提取——灰度重心法
拍频造成的轻微震荡
二进制加法
OC-块对象
UNIX哲学
数论知识点
PTA 求一批整数中出现最多的个位数字
STM32使用静态队列保存数据
fork creates multiple child processes
【Data augmentation in NLP】——1
PTA习题 阶梯电价(C)
通关SQLilab靶场——Less-1思路步骤