前端必备技能揭秘:防抖与节流,提升网页性能神器!

83 阅读5分钟

防抖节流是什么

防抖(Debounce)和节流(Throttle)是前端开发中常用的性能优化技术,用于控制事件触发频率,提升用户体验和减轻服务器负担。

  1. 防抖(Debounce):防抖的原理是在事件触发后延迟一段时间执行操作,如果在这段时间内再次触发了同样的事件,则重新计时。这样可以确保只有在事件触发完成后的一段时间内没有再次触发时,才执行相应的操作。举个例子,当用户在搜索框中输入关键词时,可以使用防抖技术延迟发送请求,以避免在用户输入过程中频繁发送请求,减轻服务器压力。
  2. 节流(Throttle):节流的原理是规定在一段时间内只能触发一次事件,不管触发频率有多高,都会在规定的时间间隔内执行一次操作。举个例子,当用户在页面上滚动时,可以使用节流技术控制滚动事件的触发频率,确保在一段时间内只处理一次滚动事件,以提高页面的流畅性和响应速度。

现实中的例子举例:

  1. 用户窗口调整:当用户调整浏览器窗口大小时,可以使用防抖技术确保只在用户停止调整窗口大小后才执行相应的操作,如重新布局页面或重新计算元素位置。
  2. 按钮点击事件:当用户点击某个按钮时,可以使用节流技术确保在一段时间内只执行一次点击事件处理函数,避免用户多次点击按钮导致重复操作或触发频繁的网络请求。
  3. 鼠标移动事件:当用户在页面上移动鼠标时,可以使用防抖技术确保只在用户停止移动鼠标后才执行相应的操作,如更新鼠标位置相关的元素或执行复杂的计算操作。

游戏中的例子举例:

  1. 防抖:英雄联盟中英雄按了B键回城,在回城的过程中,再次按下B键回城可以打断之前的回城动作,重新开始回城。

  2. 节流:英雄联盟中英雄使用了闪现,所以三分钟内无法再次使用闪现(函数)

通过使用防抖和节流技术,可以有效地控制事件的触发频率,减少不必要的操作或请求,提升用户体验和页面性能。

防抖示例:

const debounce = (fn, delay) => {
  let timer = null
  return (...args) => {
    clearTimeout(timer) // 取消之前的等待
    timer = setTimeout(() => {
      fn.call(undefined, ...args) // 等待时间结束后执行 fn
    }, delay)
  }
}

首先,debounce 函数接受两个参数:fn 是需要执行的操作函数,delay 是延迟时间,表示在多久之后执行操作。

在函数内部,我们定义了一个名为 timer 的变量,用于记录定时器的引用。初始时,它被设置为 null,表示没有定时器在运行。

然后,debounce 函数返回一个新的函数。这个函数会被调用时,会执行以下步骤:

  1. 调用 clearTimeout(timer),用于取消之前的等待。

    • 如果前一个定时器还在运行,通过 clearTimeout 函数可以清除之前的定时器,确保不会执行之前的操作。
  2. 通过 setTimeout 函数设置一个新的定时器,在延迟时间 delay 后执行操作函数。

    • 这样,在每次函数被连续调用时,只有最后一次调用会触发定时器。
    • 当定时器完成后,会执行传入的操作函数 fn,并将之前保存的参数 args 传递给它。
    • 通过 fn.call(undefined, ...args) 来调用操作函数 fn,并将 args 数组中的元素作为参数传递给它。

这样,通过防抖函数,当连续触发操作时,只有在延迟时间内没有新的操作触发时,才会执行操作函数。这可以用于限制频繁触发的操作,例如搜索框输入、窗口调整大小等,以减少不必要的计算或请求,并提升用户体验。

节流(普通版)示例:

const throttle = (fn, time) => {
  let cooldown = false
  return (...args) => {
    if (cooldown) return
    fn.call(undefined, ...args)
    cooldown = true
    setTimeout(() => {
      cooldown = false
    }, time)
  }
}

首先,throttle 函数接受两个参数:fn 是需要执行的操作函数,time 是时间间隔,表示在多久之后可以再次触发操作。

在函数内部,我们定义了一个名为 cooldown 的变量,用于记录当前是否处于冷却状态(即是否可以执行操作)。

然后,throttle 函数返回一个新的函数。这个函数会被调用时,会执行以下步骤:

  1. 如果 cooldown 变量为 true,即处于冷却状态,说明上次的操作还在时间间隔内,直接返回,不执行操作。

  2. 如果 cooldown 变量为 false,即不处于冷却状态,可以执行操作。

    • 首先,通过 fn.call(undefined, ...args) 来调用传入的操作函数 fn,并将 args 数组中的元素作为参数传递给它。
    • 然后,将 cooldown 变量设置为 true,表示开始进入冷却状态。
    • 接着,通过 setTimeout 函数设置一个定时器,在指定的时间间隔 time 后,将 cooldown 变量重新设置为 false,以表示冷却状态结束。

这样,通过节流函数,当连续触发操作时,只有第一次触发会立即执行,后续的触发会在指定的时间间隔内被忽略,直到冷却状态结束后才会再次执行。这可以用于限制频繁触发的操作,例如滚动事件、鼠标移动事件等,以提升性能和减少不必要的计算或请求。

节流(简洁版)示例:

const throttle = (fn, time) => {
  let timer = null
  return (...args) => {
    if (timer) return
    fn.call(undefined, ...args)
    timer = setTimeout(() => {
      timer = null
    }, time)
  }
}