「这是我参与2022首次更文挑战的第10天,活动详情查看:2022首次更文挑战」。
在谈论函数防抖与节流之前,我们首先了解一下这些概念是怎么来的。
首先我们知道js中有一些事件,比如scroll事件,大家不妨测试一下代码如下,当滚动一下屏幕,就会发现这个事件会被触发很多次
window.onscroll = function(){
console.log('我滚动了屏幕');
}
实际上,我们在绑定事件的过程中,还应当关注其性能问题,因为scroll与其他鼠标键盘等事件相比,触发的频次高很多,并且间隔的时间非常近。如果scroll事件中涉及到一些dom操作或者位置计算等,就会引发大量的页面重绘和回流,从而导致浏览器掉帧、CPU使用率增加,最终影响用户体验,一般我们做开发时,都是配置较好的电脑,也就是说可能执行完这个事件花费10ms,那么普通配置的电脑呢,可能要花30ms,影响页面的响应时间,而这往往会在我们开发的过程中被忽视。那么这里我们就是来介绍如何优化这个问题。
方案1:函数防抖:每次触发这个事件的时候,都设置一个延时器来延迟执行,并且在启动延时器之前清除之前的延时器,代码如下
var t ;
window.onscroll = function () {
clearTimeout(t) ;
t = setTimeout(function () {
console.log('我滚动了屏幕');
},300)
}
这样的话,拉动滚动条时,事件执行次数明显变少,但是如果不断的拉动,事件不断被触发,就会发现延时器不断被推迟,也就是这个事件迟迟不被执行。
方案2:函数节流:每次触发这个事件的时候,做一个判断,在执行事件的时候,不允许事件再次触发,等到要执行的事件完成之后才可以再次触发此事件。
var t ;
var flag = true ;
window.onscroll = function () {
if(flag) {
flag = false ;
setTimeout(function () {
console.log('我滚动了屏幕');
flag = true ;
},300)
}
}
这样的话,相当于如果一直拉动滚动条的话,每300ms才会执行一次,在这300ms期间不会重新执行。
小结:
函数防抖: 将多次事件合并成了一个操作,本质上就是在维护一个延时器,规定在指定的时间后触发函数,但是如果在这个期间,事件被再次触发,就会取消之前的延时器从而重新计算时间,这样一来,实际上也就是只有最后一次事件才会执行。
函数节流: 一段时间内,只执行一次事件,本质就是判断是否该事件正在执行。
区别: 函数节流不管事件触发有多少次,都会保证在规定时间内一定会执行一次真正的事件处理函数,而函数防抖只是在最后一次事件后才触发一次函数。
使用场景:
1.滚动事件或者窗口大小发生改变时,实际上只需要在用户停止操作的时候,执行一次函数,也就是用户可以一直拉动滚动条或者改变窗口的大小,直到满意的位置或大小停止后才去触发这个函数,因此用函数防抖更合适
2.在无限加载页面的场景下,比如淘宝商品列表可以一下向下刷新数据,这种场景下,我们需要在用户滚动屏幕的时候,每隔一段时间做一次ajax请求,而不是等用户停止滚动页面之后再请求数据,这样用户等待的时间就变长了,因此用函数节流更合适。