防抖与节流

  • Post author:
  • Post category:其他




1.防抖与节流为何出现以及是什么?

在日常开发中,我们经常会遇到:如input输入框监听事件,点击按钮事件,鼠标移动事件,视图窗口缩放事件等事件,如果这些事件不做限制的话,会不断触发相应的事件极大的浪费资源,降低前端的性能

这个是时候我们可以引入

防抖(debounce)



节流(throttle)

来帮助我们极大的减少高频事件的触发,减少资源的浪费和提高性能;防抖与节流就是为了防止用户高频率的触发某种操作而产生的



2.防抖

防抖:debounce 就是规定在一定的

时间后

触发,如果在此时间内事件被触发,则时间重新计算;例如:定义在3秒后触发事件,3秒内你又触发事件,则时间重新计算,从0开始,还是3秒后触发


适合的场景

:input输入框的监听,我们只希望最后输入完才会去触发查询相应的事件;还有按钮的点击,我们只希望频繁的点击按钮,在最后一次点击后才会触发事件…

我们拿点击按钮触发事件为例:不加防抖的情况:

index.html文件代码如下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <button style="color:red;text-align: center;" id="btn">按钮点击我</button>
    <script src="./index.js"></script>
</body>
</html>

index.js代码如下:

// 获取按钮的dom元素并且绑定原生点击事件
let btn=document.getElementById('btn')
btn.addEventListener('click',function(){
    console.log('我被点击了'+Math.random())
})

频繁的点击按钮,会发现控制台频繁的打印信息

在这里插入图片描述

加上防抖函数:

// 获取按钮的dom元素并且绑定原生点击事件
let btn=document.getElementById('btn')
// btn.addEventListener('click',function(){
//     console.log('我被点击了'+Math.random())
// })
// 防抖函数  简单的高阶函数  返回一个函数
const myDebounce=function(fn,delay){
    let timer=null  
    let ctx=this
    let args=arguments
    return function(){
        if(timer) clearTimeout(timer)
        timer=setTimeout(()=>{
            fn.apply(ctx,args)
        },delay)
    }
}
// 改造加上防抖函数
btn.addEventListener('click',myDebounce(function(){
    console.log('我被点击了'+Math.random())
},2000))

此时我们在点击按钮,会发现不管我们如何频繁的点击,控制台并不打印信息,只有停止点击按钮2秒后才会打印出第一条信息

但是我们发现此时并不合理,

我们希望第一次点击时一定触发

,此后在点击按照2秒后触发才合理,是吧?那么我们改造一下,给防抖函数加一个变量来标识是否是第一次触发,代码如下:

// 获取按钮的dom元素并且绑定原生点击事件
let btn=document.getElementById('btn')
// btn.addEventListener('click',function(){
//     console.log('我被点击了'+Math.random())
// })
// 防抖函数  简单的高阶函数  返回一个函数
const myDebounce=function(fn,delay){
    let timer=null  
    let ctx=this
    let args=arguments
    let firstClick=1
    return function(){
        if(timer) clearTimeout(timer)
        if(firstClick===1){
            fn.apply(ctx,args)
            firstClick++
        }else{
            timer=setTimeout(()=>{
                fn.apply(ctx,args)
            },delay)
        }
    }
}
// 改造加上防抖函数
btn.addEventListener('click',myDebounce(function(){
    console.log('我被点击了'+Math.random())
},2000))



3.节流


节流:

throttle,就是 在规定的一段时间后一定会执行一次,时间不会重新计算;就是每隔一定时间执行一次的意思。例如:我们定义在3秒后触发事件,就会每隔3秒触发一次事件

适合的场景是:鼠标移动事件 或者视图窗口调整 需要将多次事件改为一段时间执行一次的事件

这里我们还是以按钮的点击为例:

index.js代码如下:

// 获取按钮的dom元素并且绑定原生点击事件
let btn=document.getElementById('btn')
 
// 节流函数  简单的高阶函数  返回一个函数
const myThrottle=function(fn,delay){
   let flag=true  //作为是否执行的开关阀门
   let ctx=this
   let args=arguments
   let firstFlag=1  //第一次执行
   return function(){
    if(firstFlag===1){
        fn.apply(ctx,args)
        firstFlag++   //第一次可以执行
    }else{
        if(flag){
            setTimeout(()=>{
                fn.apply(ctx,args)
                flag=true
            },delay)
            flag=false
       }
    } 
   }
}
 
// 改造加上节流函数
btn.addEventListener('click',myThrottle(function(){
    console.log('我被点击了'+Math.random())
},2000))

点击按钮,我们会发现,第一次点击事件立马执行,然后后面疯狂点击事件,每隔2秒会打印出信息;



4.区别

防抖是多次频繁的触发,变为最后一次执行的触发;

节流是多次频繁的触发,变为每隔一段时间执行的触发;

在项目中我们根据具体的实际情况来选择使用防抖或者节流,来减少资源的浪费,优化前端的性能。

加油,学习前端每一天!!!



版权声明:本文为Jason_yuxuan原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。