快速理解与区分防抖和节流(debounce & throttle)

从事前端工作的小伙伴肯定都听说过防抖和节流,在工作中,它们常常应用于触发次数频繁的事件,例如(resize、input、scroll、mouse事件…),因为如果不采取节制,这些高频事件会频繁地执行响应函数,有时会影响性能或体验感。
那么什么是节流和防抖?它们的共同作用是控制高频事件执行响应函数的次数。假定一个场景,响应input事件输出input框的值,我们先来看看正常情况:

var inputCon = document.getElementsByTagName("input")[0]
var text = document.getElementById("text")

//正常
function handleInput() {
  let inputVal = inputCon.value
  text.innerHTML += `${inputVal}
`
}

快速理解与区分防抖和节流(debounce & throttle)_第1张图片
可以看到,随着input事件的频繁触发,每一次都执行了一次响应函数输出input值。

防抖(debounce)

事件触发后隔一段时间才执行响应函数,若等待期间内事件被再次触发,则重新计时,直至最后一次触发事件成功执行响应函数。

通俗理解:不停地重新计时,将短时间内的高频事件节制为只执行一次函数,且是在最后一次触发事件时执行。
实现方法:事件触发后,判断如果存在定时器,则清空它;同时重新定义定时器,等待执行函数。
代码举例:

let timer = null
function handleInput() {
  if(timer) {
    clearTimeout(timer)
  }
  timer = setTimeout(() => {
    let inputVal = inputCon.value
    text.innerHTML += `${inputVal}
`
},2000) }

快速理解与区分防抖和节流(debounce & throttle)_第2张图片
"123"是连贯输入,间隔小于2s,所以不输出,函数直到"3"input事件定时器结束才执行,后面的"4567890"同理。短时间内每一次input都会打断上一次input,清空并重新定时,直至最后一次input的2s结束才执行函数。个人常常用于监听窗口resize事件,毕竟resize事件十分高频。

节流(throttle)

事件触发后一段时间才执行响应函数,若等待期间内事件被再次触发,则忽略不执行函数,直至期限结束执行完函数才关闭定时开始下一次。

通俗理解:将高频事件节制为每个规定时间段只执行一次函数。就像水龙头,想省水,肯定是希望规定时间段内水流小。
实现原理:事件触发后判断如果定时器为空,则启动定时器,等待时间到执行函数并清空定时器。
有两种实现方式,一种是定时器,另一种是时间戳,异曲同工。先看第一种(定时器):

let timer = null
function handleInput() {
  if(!timer) {
    timer = setTimeout(() => {
      let inputVal = inputCon.value
      text.innerHTML += `${inputVal}
`
timer = null },2000) } }

第二种(时间戳):

let previous = 0
function handleInput() {
  let now = Date.now()
  if (now - previous > 2000) {
    let inputVal = inputCon.value
    text.innerHTML += `${inputVal}
`
previous = now } }

快速理解与区分防抖和节流(debounce & throttle)_第3张图片
个人比较习惯使用定时器,因为直观和习惯,但也不是说时间戳不好,各有所爱吧,原理都相同,就是在事件触发后规定时间内只容许执行一次函数。"1234567890"连续触发input时,每2s才会执行一次函数并开始下一次事件定时。

总结:防抖是控制执行函数次数;节流控制执行函数频率

你可能感兴趣的:(前端笔记)