认识防抖和节流
防抖
防抖,顾名思义,防止抖动,以免把一次事件误认为多次,敲键盘就是一个每天都会接触到的防抖操作。
想要了解一个概念,必先了解概念所应用的场景。在 JS 这个世界中,有哪些防抖的场景呢
- 登录、发短信等按钮避免用户点击太快,以致于发送了多次请求,需要防抖
- 调整浏览器窗口大小时,resize 次数过于频繁,造成计算过多,此时需要一次到位,就用到了防抖
- 文本编辑器实时保存,当无任何更改操作一秒后进行保存
只有在某个时间内,没有再次触发某个函数时,才真正的调用这个函数
- 当事件触发时,相应的函数并不会立即触发,而是会等待一定的时间
- 当事件密集触发时,函数的触发会被频繁的推迟
- 只有等待了一段时间也没有事件触发,才会真正的执行响应函数
节流
在飞机大战的游戏中,我们按下空格会发射一个子弹:
- 即使按下的频率非常快,子弹也会保持一定的频率来发射;
- 比如1秒钟只能发射一次,即使用户在这1秒钟按下了10次,子弹会保持发射一颗的频率来发射;
- 但是事件是触发了10次的,响应的函数只触发了一次;
在某个时间内,某个函数只能被触发一次;
使用场景依然是密集的事件触发,但是这次密集事件触发的过程,不会等待最后一次才进行函数调用,而是会按照一定的频率进行调用
对比
- 防抖:防止抖动,单位时间内事件触发会被重置,避免事件被误伤触发多次。代码实现重在清除之前的计时器
clearTimeout
- 节流:控制流量,单位时间内事件只能触发一次。代码实现重在开锁关锁
timer=timeout; timer=null
函数节流不管事件触发有多频繁,都会保证在规定时间内一定会执行一次真正的事件处理函数,而函数防抖只是在最后一次事件后才触发一次函数。 比如在页面的无限加载场景下,我们需要用户在滚动页面时,每隔一段时间发一次 Ajax 请求,而不是在用户停下滚动页面操作时才去请求数据。这样的场景,就适合用节流技术来实现。
实现防抖函数
定义debounce
函数要求传入两个参数
- 需要处理的函数fn
- 延迟时间
通过定时器来延迟传入函数fn的执行
- 如果在此期间有再次触发这个函数,那么
clearTimeout
取消这个定时器 - 如果没有触发,那么在定时器的回调函数中执行即可
function debounce(fn, delay) {
var timer = null;
return function() {
if (timer) clearTimeout(timer);
timer = setTimeout(function() {
fn();
}, delay);
}
}
var timer=null
只是对变量timer
进行初始化操作
这里还用到了函数闭包,只要return
后面返回的函数没有执行完毕,则timer
变量会一直保持在栈空间中,不会被销毁。所以在这里timer
变量只会被初始化一次,也就是第一次执行debounce
防抖函数才会执行var timer=null
的初始化赋值操作。
实际运用:调整Echarts的大小
mounted() {
var that = this;
var timer = null;
window.addEventListener("resize", function() {
var delay = 500;
if (timer) clearTimeout(timer);
timer = setTimeout(function() {
let myChart = echarts.init(document.getElementById(that.id));
myChart.resize();
}, delay);
});
}
第一次timer
初始化为空,if(timer)
里面的内容不执行,对timer
进行赋值定时器。
如果在定时器结束之前(此时定时器中的函数没有被执行)再次激活监听的事件,timer
不为空,所以之前的定时器被清除,然后又去设置新的定时器,直到新的定时器时间过了才执行函数。
实现节流函数
节流函数的默认实现思路我们采用时间戳的方式来完成:
- 我们使用一个
last
来记录上一次执行的时间 - 每次准备执行前,获取一下当前的时间
now
- 如果
now - last > interval
,那么函数执行,并且将now赋值给last即可
function throttle(fn, interval) {
var last = 0;
return function() {
// this和argument
var _this = this;
var _arguments = arguments;
var now = new Date().getTime();
if (now - last > interval) {
fn.apply(_this, _arguments);
last = now;
}
}
}
参考
https://mp.weixin.qq.com/s/qy... (主要看这个)
https://blog.csdn.net/YuT_ian...
https://zhuanlan.zhihu.com/p/...
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。