一、为什么需要防抖和节流呢?
在进行滚动scroll、窗口resize、输出框内容校验等操作的时候,如果事件处理函数调用的频率无限制,就会加重浏览器的负担,导致用户体验非常差。所以为了防止事件在短时间内多次触发,就产生了防抖和节流这两种解决方案。
二、防抖
- [防抖的原理 ] 当持续触发事件时,一定时间段内没有再触发事件,事件处理函数才会执行一次,如果设定的时间到来之前,又一次触发了事件,就重新开始延时。(简单的说,当一个函数连续触发,只执行最后一次。)
- [防抖的实现方式 ] 每次触发事件时设置一个延迟调用方法,并且取消之前的延时调用方法。
假如手抖,点了两下,那我认为头一下点的时候是手抖了,最后一下点的才是真的,那能不能只发一次请求?
//防抖,延时一会儿再去请求,所以可以用到定时器
var btn = document.querySelector('button');
btn.onclick = function() {
setTimeout(() => {
console.log('发送请求了...');
}, 1000);
}
// 延迟一秒再去发送请求,这样的话就不会太频繁
频繁去点,会发现没用,每一次点都是一个新的setTimeout,发了一个新的请求。那点了十次,就是发了十个延时一秒钟的请求,
在系统任务里面,有10个延时的任务,都是1秒后执行,所以等到1秒之后它们的请求就都执行出来了,没有起到防抖的作用。
应该达到什么样的作用:点了很多次,最终只执行一次,所以setTimeout只需要保留最后一次,前面的setTimeout是要取消掉的。代码实现如下:
var btn = document.querySelector('button');
var timer = null;
btn.onclick = function() {
clearTimeout(timer); //每次点之前把上一个定时器给清掉
timer = setTimeout(() => {
console.log('发送请求了...');
}, 1000);
}
- [防抖的应用场景 ] 函数防抖一般用在什么情况之下呢?一般用在,连续的事件只需触发一次回调的场合。具体有:
- 搜索框搜索输入。只需用户最后一次输入完,再发送请求;
- 用户名、手机号、邮箱输入验证;
- 浏览器窗口大小改变后,只需窗口调整完后,再执行resize事件中的代码,防止重复渲染。
三、节流
-
[ 节流的原理] 当持续触发事件时,保证一定时间段内只调用一次事件处理函数。(简单来说,在规定时间内只能执行一次。)
-
[ 节流的实现方式]
var btn = document.querySelector('button'); var flag = true; //创建一个节流阀,默认阀门是开着的,然后水一直往下流 btn.onclick = function() { if (flag) { flag = false; //一进来我们可以把阀门关小一点,然后再发了一次请求 console.log('发送请求了......'); 当水龙头的水一直往下流,这十分的浪费水,所以我们可以把龙头关小一点,让水一滴一滴往下流,每隔一段时间掉下来一滴水,所以需要用到定时器 setTimeout(() => { flag = true; }, 1000); } -
[节流的应用场景 ]节流就是限制一个函数在一段时间内只能执行一次,过了这段时间,在下一段时间又可以执行一次。应用场景如:
- 输入框的联想,可以限定用户在输入时,只在每两秒钟响应一次联想。
- 搜索框输入查询,如果用户一直在输入中,没有必要不停地调用去请求服务端接口,等用户停止输入的时候,再调用,设置一个合适的时间间隔,有效减轻服务端压力。
- 表单验证
- 按钮提交事件