一个跨行前端的小白菜随笔 —— 防抖函数

在前端开发过程中,我们常遇到一些问题。比如在实现响应式布局时,我们需要根据浏览器窗口的宽度,设定不同的排版模式。或者是在使用scroll时,需要时刻监听函数。

但是在不断缩放浏览器窗口、不断拖动scroll时,会不断地触发它的监听函数。这样对我们浏览器性能并不友好。因此我们想让它在缩放窗口、拖动scroll时,不会触发函数,只有等操作完成约100ms后,才开始触发函数。

 

这里,我们用Vue来举一个简单的🌰。

 

//在mounted中,添加一个监听浏览器窗口的函数
  mounted() {
    window.addEventListener('resize',()=>{
      console.log('211');
    })
  }

 

拖动时,可以看到浏览器的情况

 

 

 

这里面有个问题,就是如何判定拖动停止?

为了搞清楚这个问题,我们不妨观察一下这个函数里面发生的情况:当拖动浏览器缩放时,函数里面的事件不断执行。那我们假设在里面设置一个计数器,当事件执行的时候,计算器+1,当计数器有超过100ms没有+1时,执行resize 事件。但这又显然进入了一个悖论,因为定时器执行,也会消耗浏览器性能,所以不可取。

那么换个思路,我们还是设置一个100ms的定时操作,如果后续要不断执行这个操作,那么我们就不断取消这个操作,总之只保留最终只执行一次这个操作。显然,需要取消操作,那就需要涉及到定时函数setTimeout()。另外,因为resize 事件肯定会不断执行,但事件里的操作 (console.log('211'))却涉及到取消、执行,说明resize事件内部之间有某种关系,这就涉及到闭包。

mounted() {
window.addEventListener('resize', ()=>{
      let Event = null                 //设定一个Event操作事件   
      return function (){         
if (Event !== null){            //如果执行了操作事件,立马清空
          clearTimeout(Event)
        }
        Event  =  setTimeout(()=>{        //重新再执行一次操作事件
          console.log('211')
        },300)
      }
    })
}

不过。。。似乎结果并不理想

 

 

 问题出在了resize事件的匿名函数身上,我们修改下

function handl(){                  
      let Event = null
      return function (){
        if (Event !== null){
          clearTimeout(Event)
        }
        Event  =  setTimeout(()=>{
          console.log('213')
        },300)
      }
    }
    
    window.addEventListener('resize', handl())

也可以改成这样 匿名函数的形式

window.addEventListener('resize',(() =>{
      let Event = null
      return function (){
        if (Event !== null){
          clearTimeout(Event)
        }
        Event  =  setTimeout(()=>{
          console.log('213')
        },300)
      }
    })())

 

问题解决了

 

 从上面的函数中,我们可以提炼出一个防抖函数

function debounce(fn,time){           //防抖函数
      let Event = null
      return function (){
        if (Event !== null){
          clearTimeout(Event)
        }
        Event  =  setTimeout(fn,time)
      }
    }

    window.addEventListener('resize', debounce(()=>{
      console.log('121');
    },300))

 

posted @ 2020-10-24 00:01  风中逆羽  阅读(145)  评论(0)    收藏  举报