当前位置:网站首页>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
}
- 后期优化返回值 , 以及取消功能
边栏推荐
- Semaphore SIGCHLD use, how to make the parent that the child performs over, how to make the distinction between multiple child processes. The end
- x86 Exception Handling and Interrupt Mechanism (1) Overview of the source and handling of interrupts
- ACM01背包问题
- win10 outlook邮件设置
- es6对象迭代器iterator
- Installation of gdb 10.2
- FreeRTOS列表和列表项源码分析
- Chinese valentine's day?Programmers don't exist
- PAT1013 并查集 DFS(查找联通分量的个数)
- 爱可可AI前沿推介(8.9)
猜你喜欢
激光条纹中心提取——Steger
wait系统调用
PTA习题 分类统计字符个数(C)
抗积分饱和 PID代码实现,matlab仿真实现
enum in c language
x86 Exception Handling and Interrupt Mechanism (1) Overview of the source and handling of interrupts
This application has no explicit mapping for /error, so you are seeing this as a fallback
【VIBE: Video Inference for Human Body Pose and Shape Estimation】论文阅读
双向链表的各种操作
Cesium加载三维模型数据
随机推荐
[现代控制理论]6_稳定性_李雅普诺夫_Lyapunov
redis主从复制
mysql + redis + flask + flask-sqlalchemy + flask-session 配置及项目打包移植部署
【概率论】一元概率分布的平均化
【Robustness of VQA-1】——2019-EMNLP-Don’t Take the Easy Way Out
基于STM32F103移植FreeRTOS
OC-块对象
MySQL的MVVC多版本并发控制机制
VS Code有趣插件
【DB运营管理/开发解决方案】上海道宁为您提供提高工作便利性的集成开发工具——Orange
PAT1014 未解决
API接口是什么?API接口常见的安全问题与安全措施有哪些?
拍频造成的轻微震荡
通关SQLilab靶场——Less-1思路步骤
ACM最长不下降子序列问题
win10 outlook邮件设置
PTA 指定位置输出字符串(c)
ZOJ1298(单源最短路径)
win10右键文件,一直转圈
学生成绩查找系统