防抖

11 天前(已编辑)
5

防抖

让一个函数在触发后,等待指定时间再执行;如果在等待期间函数再次被触发,则重新计时

标准实现

/**
 * 防抖函数
 * @param {Function} func - 需要防抖的目标函数
 * @param {number} wait - 等待时间(毫秒),默认300ms
 * @returns {Function} - 包装后的防抖函数
 */
function debounce(func, wait = 300) {
  // 保存定时器ID,用于清除计时
  let timeoutId = null;
  // 返回包装后的防抖函数
  return function (...args) {
    // 保存当前上下文(比如DOM事件中的this)
    const context = this;
    // 核心逻辑:每次触发时,先清除之前的定时器,重新计时
    if (timeoutId) clearTimeout(timeoutId);
    // 新建定时器,等待指定时间后执行目标函数
    timeoutId = setTimeout(() => {
      // 执行原函数,传递上下文和参数,避免this丢失、参数丢失
      func.apply(context, args);
      // 执行后清空定时器ID(非必需,但更规范)
      timeoutId = null;
    }, wait);
  };

react hook封装

import { useCallback, useRef } from 'react';

/**
 * React 防抖 Hook
 * @param {Function} func - 需要防抖的目标函数
 * @param {number} wait - 等待时间(毫秒),默认300ms
 * @returns {Function} - 包装后的防抖函数
 */
function useDebounce(func, wait = 300) {
  // 用 useRef 保存定时器ID(避免每次渲染重置)
  // 其次是我们在settimeout中用了这个变量,为了避免闭包陷阱,还是加上ref
  const timeoutIdRef = useRef(null);
  // 用 useRef 保存最新的函数引用(避免依赖变化导致防抖失效)
  // 其次是我们在settimeout和usecallback中用了这个变量,为了避免闭包陷阱,还是加上ref
  const funcRef = useRef(func);

  // 每次渲染更新函数引用,保证拿到最新的func
  funcRef.current = func;

  // 用 useCallback 缓存防抖函数,避免组件重渲染时重新创建
  const debouncedFunc = useCallback((...args) => {
    // 保存当前上下文(React 中通常是组件实例/事件对象)
    const context = this;

    // 清除之前的定时器,重新计时
    if (timeoutIdRef.current) {
      clearTimeout(timeoutIdRef.current);
    }

    // 新建定时器
    timeoutIdRef.current = setTimeout(() => {
      // 执行最新的函数引用
      funcRef.current.apply(context, args);
      // 执行后清空定时器ID
      timeoutIdRef.current = null;
    }, wait);
  }, [wait]);

  // 清理函数:组件卸载/防抖函数更新时,清除未执行的定时器
  const cancelDebounce = useCallback(() => {
    if (timeoutIdRef.current) {
      clearTimeout(timeoutIdRef.current);
      timeoutIdRef.current = null;
    }
  }, []);

  // 返回防抖函数和取消方法
  return [debouncedFunc, cancelDebounce];
}

export default useDebounce;

使用社交账号登录

  • Loading...
  • Loading...
  • Loading...
  • Loading...
  • Loading...