防抖和节流:前端开发的"刹车"和"限速"

97 阅读3分钟

今天我们来聊两个前端开发中特别实用的技巧:防抖和节流。它们就像是我们网页的"刹车"和"限速"系统,能帮我们控制网页上的各种操作不要太频繁。

一、防抖:等你不抖了再干活

1. 什么是防抖?

想象一下电梯门:当有人进出时,门会一直开着,直到最后一个人进去后,门才会关上。防抖就是这个道理——它会等到你"停止抖动"(停止操作)后才执行一次。

2. 什么时候用?

  • 搜索框输入(等用户输完再搜索)
  • 提交按钮(防止用户连点)
  • 窗口大小调整(等用户调整完再计算)

3. 代码怎么写?

// 提交表单的按钮
let btn = document.getElementById('btn');
btn.addEventListener('click', debounce(handle, 1000)); // debounce函数中的this指向btn

function handle(e) {
    console.log('向后端发请求', this); // 通过显示绑定,将handle的this也指向btn
}

// 防抖核心代码
function debounce(fn, wait) {
  let timer = null; // 用来记时的"沙漏"
  
  return function(...args) {
    clearTimeout(timer); // 每次有人点按钮,就把之前的沙漏重置
    
    // 开启沙漏
    timer = setTimeout(() => {
      fn.call(this, ...args); // 沙漏漏完,才真正干活
    }, wait);
  };
}

4. 实现要点

  • 闭包保存定时器:使用闭包保存timer变量,确保每次触发都能访问到同一个定时器
  • 清除上一次定时器:每次触发时先清除之前的定时器,确保只有最后一次触发有效
  • this和参数处理:使用call方法确保函数执行时的this指向正确,并通过剩余参数...arg传递所有参数(包括事件参数event)

二、节流:再急也得按节奏来

1. 什么是节流?

就像水龙头,你开得再大,水流也是均匀的。节流就是让频繁的操作变成有规律的执行,比如每2秒最多执行一次。

2. 什么时候用?

  • 页面滚动加载更多
  • 鼠标移动跟踪
  • 游戏按键控制

3. 代码怎么写?

// 绑定滚动事件
window.addEventListener('scroll', throttle(checkPosition, 200)); // throttle函数中的this指向window

function handle(e) {
    console.log('向后端发请求', this); // 通过显示绑定,将handle的this也指向window
}

// 节流核心代码
function throttle(fn, wait) {
  let lastTime = 0; // 上次执行的时间
  
  return function(...args) {
    const now = Date.now(); // 现在的时间
    
    // 如果距离上次执行已经超过等待时间
    if (now - lastTime >= wait) {
      fn.call(this, ...args); // 可以执行了
      lastTime = now; // 更新上次执行时间
    }
  };
}

4. 实现要点

  • 时间戳记录:使用Date.now()记录当前时间,利用闭包记录上一次执行时间
  • 时间差判断:只有在当前时间与上一次执行时间的差值大于等待时间时,才执行fn函数并更新上一次执行时间
  • this和参数处理:和防抖类似,使用call方法确保函数执行时的this指向正确,并通过剩余参数...arg传递所有参数

三、生活小例子帮你理解

  1. 防抖:就像你妈妈叫你吃饭,你总是说"马上来",最后妈妈等到你5分钟没再说"马上来"了,才真的把饭端上桌。

  2. 节流:就像你玩游戏按技能键,按得再快,技能也是有冷却时间的,不能无限放。

四、两者简单对比

防抖节流
特点等你不操作了才执行固定时间执行一次
例子搜索框输入完才搜索游戏角色移动
效果只执行最后一次均匀执行

五、实战小贴士

  1. 表单提交:防抖+禁用按钮双保险最好

    button.addEventListener('click', debounce(() => {
      button.disabled = true; // 先禁用按钮
      submitForm().finally(() => {
        button.disabled = false; // 完成后启用
      });
    }, 500));
    
  2. 滚动加载:用节流效果更好

    window.addEventListener('scroll', throttle(loadMore, 300));
    
  3. 搜索建议:防抖最适合

    searchInput.addEventListener('input', debounce(fetchSuggestions, 300));
    

记住这两个小技巧,能让你的网页变得更流畅,用户体验更好!刚开始可能不太习惯,多用几次就熟练啦!