节流和防抖在我们平时的项目中挺常用的,也是面试中经常会被提问的知识点,今天我们一起来学习一下。
节流
简单理解就是:控制函数每隔n秒执行一次。
作用
防止用户高频率的触发事件,刚好这个事件又需要处理大量的计算和渲染而带来的性能问题。
应用场景
- onscroll
- onresize
- mousemove
- touchmove
- ...
示例
这边我们以onscroll
来写个例子,加深理解。
比如有这样一个场景:我们需要判断浏览器滚动条滚动到底部的时候去动态加载一些数据,可能我们直接就会写上以下的代码:
let obj = document.querySelector('.throttle-test');
let _count = 0;
obj.onscroll = function () {
// 假设已经滚动到底部了,我们给_count加1。
_count++;
console.log('执行次数:' + _count);
}
复制代码
我们来看下浏览器的打印结果,看以下gif图:
可以看到,函数执行了20次,很显然这并不是我们想要的,因为onscroll
事件并不会等你滚动到底部了再去触发事件,而是会不间断的触发,这就很容易引发一些性能问题,这时候就需要用到节流了。
我们把代码做下修改:
let obj = document.querySelector('.throttle-test');
let _count = 0;
let _canRun = true;
obj.onscroll = function () {
if (!_canRun) {
return false;
}
_canRun = false;
setTimeout(function () {
// 假设已经滚动到底部了,我们给_count加1。
_count++;
console.log('执行次数:'+_count);
_canRun = true;
}, 500);
}
复制代码
通过以下gif图,我们可以看到,函数最终只执行了2次。
通过一个定时器,我们控制函数每隔500毫秒再执行一次,大大降低了执行频率,从而提升性能。
节流概念理解
节流跟防抖,它们既有相似之处但又有所不同,很容易混淆。这里通过比喻来加深理解,先来说说节流。
节流的概念可以想象一下水坝,你建了水坝在河道中,不能让水流动不了,你只能让水流慢些。换言之,你不能让用户的方法都不执行。(个人比较喜欢这个比喻,因为它很形象的说出了跟防抖的区别。)
防抖
控制函数在n秒内只能执行一次,如果用户在n秒内重复的触发事件,则重新计时且函数不会被执行,只有等到用户不再触发事件的时候才去执行一次。
作用跟节流
类似,也是为了防止用户高频率的触发事件所引发的性能问题。
防抖概念理解
可以想象一下做电梯,当有人进入电梯(触发事件),那电梯将在10秒后出发(执行事件),这时如果又有人进入电梯了(在10秒内再次触发了事件),我们又得重新等10秒才能触发(重新计时)。
示例
有个文本框让用户填写用户名,当用户输入字符时,我们需要实时发请求到后台去验证用户名是否有重复的。实际上,在加入防抖机制前,用户输入helloworld
后,我们已经发送了10次请求了,很显然是不可取的。
看代码:
let obj = document.querySelector('#testInput'); // 获取文本输入框
let _count = 0;
obj.onkeyup = function () {
_count++;
console.log('执行次数:' + _count);
}
复制代码
我们来给代码加入防抖机制:
我们只能假设用户在停顿n秒内没有再触发事件,我们就判定用户已经输入完成了,这时再发送请求。
看代码:
let obj = document.querySelector('#testInput');
let timer = null;
let _count = 0;
obj.onkeyup = function () {
clearTimeout(timer); // 清除定时器,重新计时
timer = setTimeout(function () {
_count++;
console.log('执行次数:'+_count);
}, 800);
}
复制代码
通过动图,可以看到,当我一直输入的时候,事件是不会被触发的,直到我停止输入才会触发一次。
实现思路:我们把目标代码放入到一个定时器里,如果事件被频繁的触发,目标代码将不会被执行。为什么不执行呢,因为我们前面加了clearTimeout
。相当于中途不断的有人进入电梯,电梯又得重新倒计时10秒才会启动一样,直到用户没再输入了(没人再进入电梯了),这时候目标代码才会按照我们设定的时间再去执行一次(电梯才会启动)。
节流和防抖的区别
- 节流:目标代码会按照我们设定的时间间隔即每隔n秒就执行一次
- 防抖:在用户不触发事件时,才去执行目标代码,并且抑制了本来在事件中要执行的动作;当事件被一直触发的情况下,目标代码有可能不会被执行
- 函数节流会用在比
input
,keyup
更频繁触发的事件中,如resize
,touchmove
,mousemove
,scroll
。节流
会强制函数以固定的速率执行。因此这个方法比较适合应用于动画相关的场景。
最后
感谢您的阅读,希望对你有所帮助。文中如果有描述不当的地方,烦请指正,感激不尽。 另外文中所演示的代码仅用来测试使用,并不适合用在实际开发中,实际开发可以使用Lodash
库中的节流
和防抖
方法,这里就不贴代码了,毕竟考虑的比较全面哈。
Lodash
库的地址:
节流:www.lodashjs.com/docs/4.17.5…
防抖:www.lodashjs.com/docs/4.17.5…
关注
欢迎大家关注我的公众号前端帮帮忙
,一起交流学习,谢谢~