首页 > 其他分享 >react中怎么实现防抖Debounce和节流Throttle

react中怎么实现防抖Debounce和节流Throttle

时间:2024-12-22 23:28:16浏览次数:7  
标签:防抖 return Debounce value delay window Throttle useEffect const

1.防抖 (Debounce):

// 1. 自定义 Hook 实现防抖
import { useState, useEffect } from 'react';

function useDebounce<T>(value: T, delay: number = 300): T {
    const [debouncedValue, setDebouncedValue] = useState<T>(value);

    useEffect(() => {
        // 设置定时器
        const timer = setTimeout(() => {
            setDebouncedValue(value);
        }, delay);

        // 清理函数
        return () => {
            clearTimeout(timer);
        };
    }, [value, delay]);

    return debouncedValue;
}

// 2. 使用示例:搜索框
const SearchComponent = () => {
    const [searchText, setSearchText] = useState('');
    const debouncedText = useDebounce(searchText, 500);

    // 只有在 debouncedText 变化时才调用 API
    useEffect(() => {
        if (debouncedText) {
            // 发起搜索请求
            searchAPI(debouncedText);
        }
    }, [debouncedText]);

    return (
        <input
            value={searchText}
            onChange={(e) => setSearchText(e.target.value)}
            placeholder="输入搜索内容"
        />
    );
};

2.节流 (Throttle):

// 1. 自定义 Hook 实现节流
import { useState, useEffect, useRef } from 'react';

function useThrottle<T>(value: T, delay: number = 300): T {
    const [throttledValue, setThrottledValue] = useState<T>(value);
    const lastExecuted = useRef<number>(Date.now());

    useEffect(() => {
        const handler = setTimeout(() => {
            if (Date.now() - lastExecuted.current >= delay) {
                setThrottledValue(value);
                lastExecuted.current = Date.now();
            }
        }, delay);

        return () => {
            clearTimeout(handler);
        };
    }, [value, delay]);

    return throttledValue;
}

// 2. 使用示例:滚动事件处理
const ScrollComponent = () => {
    const [scrollPosition, setScrollPosition] = useState(0);
    const throttledPosition = useThrottle(scrollPosition, 200);

    useEffect(() => {
        const handleScroll = () => {
            setScrollPosition(window.scrollY);
        };

        window.addEventListener('scroll', handleScroll);
        return () => window.removeEventListener('scroll', handleScroll);
    }, []);

    useEffect(() => {
        console.log('throttled scroll position:', throttledPosition);
    }, [throttledPosition]);

    return (
        <div style={{ height: '2000px' }}>
            Scroll Position: {throttledPosition}
        </div>
    );
};

3.实际应用场景:

// 1. 实时搜索建议
const AutoComplete = () => {
    const [inputValue, setInputValue] = useState('');
    const debouncedValue = useDebounce(inputValue, 500);
    const [suggestions, setSuggestions] = useState<string[]>([]);

    useEffect(() => {
        if (debouncedValue) {
            // 获取搜索建议
            fetchSuggestions(debouncedValue)
                .then(data => setSuggestions(data));
        } else {
            setSuggestions([]);
        }
    }, [debouncedValue]);

    return (
        <div>
            <input
                value={inputValue}
                onChange={(e) => setInputValue(e.target.value)}
                placeholder="输入关键词"
            />
            <ul>
                {suggestions.map((item, index) => (
                    <li key={index}>{item}</li>
                ))}
            </ul>
        </div>
    );
};

// 2. 窗口大小调整处理
const ResponsiveComponent = () => {
    const [windowSize, setWindowSize] = useState({
        width: window.innerWidth,
        height: window.innerHeight
    });
    const throttledSize = useThrottle(windowSize, 200);

    useEffect(() => {
        const handleResize = () => {
            setWindowSize({
                width: window.innerWidth,
                height: window.innerHeight
            });
        };

        window.addEventListener('resize', handleResize);
        return () => window.removeEventListener('resize', handleResize);
    }, []);

    return (
        <div>
            Throttled Window Size: {throttledSize.width} x {throttledSize.height}
        </div>
    );
};

4.带回调的防抖函数:

// 1. 防抖 Hook 带回调
function useDebounceCallback<T extends (...args: any[]) => any>(
    callback: T,
    delay: number
): T {
    const timeoutRef = useRef<NodeJS.Timeout>();

    return useCallback(
        (...args: Parameters<T>) => {
            if (timeoutRef.current) {
                clearTimeout(timeoutRef.current);
            }

            timeoutRef.current = setTimeout(() => {
                callback(...args);
            }, delay);
        },
        [callback, delay]
    ) as T;
}

// 2. 使用示例
const SearchForm = () => {
    const handleSearch = useDebounceCallback((value: string) => {
        // 执行搜索
        console.log('Searching for:', value);
    }, 500);

    return (
        <input
            onChange={(e) => handleSearch(e.target.value)}
            placeholder="搜索..."
        />
    );
};

5.带状态的节流函数:

// 1. 节流 Hook 带状态
function useThrottleState<T>(
    initialValue: T,
    delay: number
): [T, (value: T) => void] {
    const [value, setValue] = useState<T>(initialValue);
    const lastExecuted = useRef<number>(Date.now());

    const setThrottledValue = useCallback((newValue: T) => {
        if (Date.now() - lastExecuted.current >= delay) {
            setValue(newValue);
            lastExecuted.current = Date.now();
        }
    }, [delay]);

    return [value, setThrottledValue];
}

// 2. 使用示例
const ScrollTracker = () => {
    const [scrollPos, setScrollPos] = useThrottleState(0, 200);

    useEffect(() => {
        const handleScroll = () => {
            setScrollPos(window.scrollY);
        };

        window.addEventListener('scroll', handleScroll);
        return () => window.removeEventListener('scroll', handleScroll);
    }, [setScrollPos]);

    return <div>Scroll Position: {scrollPos}</div>;
};

       关键点:

  • 防抖:等待一段时间后才执行,如果期间又触发则重新计时
  • 节流:在一定时间内只执行一次
  • 使用 useRef 保存定时器或上次执行时间
  • 使用 useEffect 清理定时器
  • 使用 useCallback 优化性能

使用场景:

  • 防抖:搜索框输入、表单验证、窗口大小调整
  • 节流:滚动事件处理、频繁点击按钮、实时保存

这些实现可以有效优化性能,减少不必要的操作。

标签:防抖,return,Debounce,value,delay,window,Throttle,useEffect,const
From: https://blog.csdn.net/m0_73574455/article/details/144654793

相关文章

  • 鸿蒙 next arkts 实现防抖节流功能
    鸿蒙next-arkts-实现防抖节流功能ClickUtilexportclassClickUtil{privateconstructor(){}privatestaticthrottleTimeoutID:number;//节流timeoutIDprivatestaticflag:boolean=false;//节流flag,true=已经进入执行状态了privatestaticdebounc......
  • 能不能实现事件的防抖和节流?
    节流节流的核心思想:如果在定时器的时间范围内再次触发,则不予理睬,等当前定时器完成,才能启动下一个定时器任务。这就好比公交车,10分钟一趟,10分钟内有多少人在公交站等我不管,10分钟一到我就要发车走人!代码如下:functionthrottle(fn,interval){letflag=true;retur......
  • 防抖和节流有什么区别傻傻分不清??一文看懂
    防抖和节流的区别防抖(Debounce)和节流(Throttle)都是用于控制函数执行频率的技术,它们主要用于优化在浏览器中频繁触发的事件(如窗口大小调整、滚动、鼠标移动、按键按下等),但它们的工作方式有所不同。防抖(Debounce)定义:防抖是指在事件被触发后,延迟一定时间后才执行回调函数,如果......
  • 分别写出防抖和节流的两个函数,并描述它们分别有什么运用场景?
    //防抖函数(Debounce)functiondebounce(func,delay){lettimer;returnfunction(){clearTimeout(timer);timer=setTimeout(()=>{func.apply(this,arguments);},delay);};}//节流函数(Throttle)functionthrottle(func,delay)......
  • SWJTU数电实验:按键防抖动设计
    本文还未验收,仅供参考,我看别人的更复杂一点,或许我的有问题。实验要求用VerilogHDL设计一个按键防抖动电路,要求用有限状态机实现。防抖动电路的输入接实验箱的按键/开关(SW0),输出接实验4计数器电路的时钟输入,实现每按一次按键(或拨一次开关)计数器加1,多......
  • JavaScript进阶--节流防抖以及技巧打磨
    打磨技巧深浅拷贝只针对引用类型浅拷贝拷贝的是值,但引用数据类型的值为地址方法:Object.assign(newobj,oldobj)Array.concat(newArr,oldArr)配合展开运算符...比较复制复制相当于把将要复制对象的地址,直接进行获取,而不是创建一个新的对象,赋予属性的值和名//实......
  • 防抖和节流(小白文)
    文章目录什么是防抖和节流?防抖(Debouncing)节流(Throttling)如何实现防抖和节流?防抖的实现节流的实现结语#防抖和节流:让你的网站跑得更快的小技巧大家好!今天我们来聊聊两个让网站跑得更快的小技巧:防抖和节流。这两个词听起来可能有点专业,别担心,我会用简单的比喻来解......
  • .NET Core中实现防抖
    利用分布式锁在ASP.NETCore中实现防抖 前言在 Web 应用开发过程中,防抖(Debounce) 是确保同一操作在短时间内不会被重复触发的一种有效手段。常见的场景包括防止用户在短时间内重复提交表单,或者避免多次点击按钮导致后台服务执行多次相同的操作。无论在单机环境中,还是在分......
  • 利用分布式锁、本地锁在ASP.NET Core中实现防抖
    前言#在Web应用开发过程中,防抖(Debounce)是确保同一操作在短时间内不会被重复触发的一种有效手段。常见的场景包括防止用户在短时间内重复提交表单,或者避免多次点击按钮导致后台服务执行多次相同的操作。无论在单机环境中,还是在分布式系统中都有一些场景需要使用它。本文将介绍......
  • 如何实现一个通用的接口限流、防重、防抖机制
    介绍最近上了一个新项目,考虑到一个问题,在高并发场景下,我们无法控制前端的请求频率和次数,这就可能导致服务器压力过大,响应速度变慢,甚至引发系统崩溃等严重问题。为了解决这些问题,我们需要在后端实现一些机制,如接口限流、防重复提交和接口防抖,而这些是保证接口安全、稳定提供服务,以......