关于前端的防抖和节流

发布于:2025-06-19 ⋅ 阅读:(12) ⋅ 点赞:(0)

给我解释下 前端开发中的防抖和节流 并举个具体的例子

防抖(Debounce)与节流(Throttle)详解

在前端开发中,防抖(Debounce) 和 节流(Throttle) 是两种优化高频触发事件的技术,用于提升性能和用户体验。它们的核心区别在于:

  • 防抖:将多次触发合并为一次执行(只执行最后一次)。
  • 节流:限制事件执行频率(按固定间隔执行)。

防抖(Debounce)

原理
  • 在事件被触发后,延迟 n 毫秒再执行回调。
  • 如果在这 n 毫秒内再次触发事件,则重新计时。
适用场景
  • 搜索框实时联想(用户停止输入后再请求)。
  • 窗口 resize 事件(只在调整结束后计算布局)。
  • 按钮提交防止重复点击。
代码示例

javascript

// 防抖函数(非立即执行版)
function debounce(fn, delay) {
  let timer = null;
  
  return function(...args) {
    // 清除上一次定时器
    if (timer) clearTimeout(timer);
    
    // 重新设置定时器,延迟执行
    timer = setTimeout(() => {
      fn.apply(this, args);
    }, delay);
  };
}

// 使用示例
const searchInput = document.getElementById('search-input');
searchInput.addEventListener('input', debounce((e) => {
  console.log('搜索:', e.target.value);
  // 发送搜索请求...
}, 300));

节流(Throttle)

原理
  • 限制一个函数在一定时间内只能执行一次。
  • 即使在这段时间内多次触发事件,也只会按固定间隔执行。
适用场景
  • 滚动加载更多数据(每滚动一定距离触发一次)。
  • 高频点击按钮(如点赞、提交)。
  • 游戏中的技能冷却。
代码示例

javascript

// 节流函数(时间戳版)
function throttle(fn, limit) {
  let lastExecTime = 0;
  
  return function(...args) {
    const now = Date.now();
    
    // 如果距离上次执行超过限制时间,则执行
    if (now - lastExecTime > limit) {
      fn.apply(this, args);
      lastExecTime = now;
    }
  };
}

// 使用示例
window.addEventListener('scroll', throttle(() => {
  console.log('滚动位置:', window.scrollY);
  // 检查是否需要加载更多数据...
}, 200));

对比与选择

特性 防抖(Debounce) 节流(Throttle)
执行时机 只在最后一次事件触发后执行 按固定间隔执行
高频触发 只执行一次 按频率执行多次
应用场景 搜索联想、窗口 resize、防止重复提交 滚动加载、高频点击、游戏技能冷却
实现方式 定时器 时间戳或定时器

高级实现(带配置选项)

防抖(支持立即执行)

javascript

function debounce(func, wait, immediate = false) {
  let timeout;
  
  return function() {
    const context = this;
    const args = arguments;
    
    const later = () => {
      timeout = null;
      if (!immediate) func.apply(context, args);
    };
    
    const callNow = immediate && !timeout;
    clearTimeout(timeout);
    timeout = setTimeout(later, wait);
    
    if (callNow) func.apply(context, args);
  };
}
节流(结合时间戳和定时器)

javascript

function throttle(func, limit) {
  let timeout;
  let lastExecTime = 0;
  
  return function() {
    const context = this;
    const args = arguments;
    const now = Date.now();
    const remaining = limit - (now - lastExecTime);
    
    if (remaining <= 0) {
      // 如果超过限制时间,立即执行
      if (timeout) {
        clearTimeout(timeout);
        timeout = null;
      }
      func.apply(context, args);
      lastExecTime = now;
    } else if (!timeout) {
      // 否则,等待剩余时间后执行
      timeout = setTimeout(() => {
        func.apply(context, args);
        lastExecTime = Date.now();
        timeout = null;
      }, remaining);
    }
  };
}

实际应用示例

1. 搜索框防抖

javascript

const searchInput = document.getElementById('search-input');

searchInput.addEventListener('input', debounce((e) => {
  // 300ms 内没有新输入时才发送请求
  fetch(`/api/search?q=${e.target.value}`)
    .then(res => res.json())
    .then(data => renderResults(data));
}, 300));
2. 滚动加载节流

javascript

window.addEventListener('scroll', throttle(() => {
  // 每 200ms 检查一次是否需要加载更多
  if (isScrollAtBottom()) {
    loadMoreData();
  }
}, 200));
3. 按钮点击防抖

javascript

const submitBtn = document.getElementById('submit-btn');

submitBtn.addEventListener('click', debounce(() => {
  // 防止重复提交,2秒内只执行一次
  submitForm();
}, 2000, true)); // 立即执行版,点击后先执行,2秒内不再执行

总结

  • 防抖:适合需要合并多次触发的场景,避免不必要的计算或请求。
  • 节流:适合需要限制执行频率的场景,如滚动、拖拽等高频事件。

合理使用这两种技术可以显著提升应用性能,减少资源浪费,改善用户体验


网站公告

今日签到

点亮在社区的每一天
去签到