当前位置:网站首页>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
}
- 后期优化返回值 , 以及取消功能
边栏推荐
猜你喜欢
无刷无霍尔BLCD电机控制
[Essence] Analysis of the special case of C language structure: structure pointer / basic data type pointer, pointing to other structures
爱可可AI前沿推介(8.9)
Chinese valentine's day?Programmers don't exist
VS Code有趣插件
x86异常处理与中断机制(2)中断向量表
Semaphore SIGCHLD use, how to make the parent that the child performs over, how to make the distinction between multiple child processes. The end
TIC2000系列处理器在线升级
【VIBE: Video Inference for Human Body Pose and Shape Estimation】论文阅读
fidder为什么不会抓包的问题
随机推荐
Win10调整磁盘存储空间详解
【Basic model】Transformer-实现中英翻译
gdb 10.2的安装
PAT1001
剖析STM32F103时钟系统
es6递归函数
Fapi_StatusType Fapi_issueProgrammingCommand使用注意事项
【精华文】C语言结构体特殊情况分析:结构体指针 / 基本数据类型指针,指向其他结构体
Installation of gdb 10.2
百钱买鸡(一)
win10右键文件,一直转圈
[现代控制理论]6_稳定性_李雅普诺夫_Lyapunov
PTA 求一批整数中出现最多的个位数字
杂记(6)
PAT1007
PAT1012
OC-块对象
MySQL执行sql语句的机制
End-to-End Object Detection with Fully Convolutional Network学习笔记
Looper 原理浅析