手写防抖、节流 hook(ts版)

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了手写防抖、节流 hook(ts版)相关的知识,希望对你有一定的参考价值。

参考技术A

不知道有多少人,简单的写了防抖、节流函数,然后遇到在 react hook 里失效的情况。

失效的原因: 每次 render 时,内部 函数会重新生成 并绑定到组件上去。

解决方案: 也很简单,使用 useCallback ,依赖传入空数组,保证 useCallback 永远返回同一个函数。

上面呢,算是这个文章的一个契机吧。

关于手写防抖和节流的思路,个人认为关键在于都是对 闭包 高阶函数 的应用,以这个为切入点去思考,手写的时候就不会脑子一片空白了。

触发事件后在 n 秒内函数只能执行一次,如果在 n 秒内又触发了事件,则会重新计算函数执行时间。

这可以用,但并不够好。想要进阶更高级的工程师,就需要将问题再想深一层,考虑到更复杂的情况,从而自身得到成长。

关于防抖函数还有功能更丰富的版本,可以看下 lodash 的 debounce 函数

连续触发事件但是在 n 秒中只执行一次函数

把两个整合一下,根据场景、需求等来决定,最后是否需要事件停止触发后定时器执行函数。

有个地方有人可能有疑问,为什么没去用 useRef 去保存 timeOut 呢?

有人可能会认为这会有问题:因为每次组件重新渲染,都会执行一遍所有的 hooks,这样 useDebounce 高阶函数里面的 timeOut 就不能起到缓存的作用(在 useDebounce 里 console.log(timeOut),每次 render 时都打印出 null)。所以 timeOut 不可靠,防抖的核心就被破坏了。

但是呢,如果你在里面的函数 debounce 里 console.log(timeOut) 会发现,打印出来的,就是之前的 timeOut ,所以是没问题的。

最后,写的过程中,ts 才是我真正花费时间思考的地方。完成后,有点微妙的满足感。

7.手写防抖和节流工具函数并理解其内部原理和应用场景

手写防抖和节流工具函数、并理解其内部原理和应用场景

防抖

        // 防抖: 一个函数 在设置的时间后执行 如果在设置的时间间隔期间再次触发 那么本次就无效 重新计算
        // 触发高频时间后n秒内只会执行一次 如果n秒高频时间内再次触发 则会重新计算时间
        // 原理 debounce 触发后 首先清除掉timeout(释放 指向空) 然后返回节流数组 利用闭包保存timeout变量 
        const debounce = (fn, time) => 
            // 利用闭包避免全局污染
            let timeout = null;
            return function () 
                if (timeout) 
                    // 在定时期间,那么清除原来计时器 重新计时(核心)
                    clearTimeout(timeout);
                
                // 设置定时器
                timeout = setTimeout(() => 
                    // 执行函数
                    fn.apply(this, arguments)
                , time);
            
        
        function clickButton(type) 
            console.log(type)
        
        //注意要绑定的事件一定是经过debouce处理过的事件,另外不能直接绑定debouce(clickButton,1000)(\'防抖\') 因为这样绑定的函数都是重新在堆里开辟的新函数,每个都会创建新的timeout(不再是闭包中被保护的timeout)
        const bindClick = debounce(clickButton, 1000);

节流

        // 节流 :重新触发不影响 原计时器 
        const throttle = (fn, time) => 
            // 利用闭包 保存当前激活状态
            let status = false;
            return function () 
                if (status) 
                    return;
                
                else 
                    status = true;
                    setTimeout(() => 
                        fn.apply(this, arguments);
                        // 重置status
                        status = false;
                    , time);
                
            
        
        const bindClick2 = throttle(clickButton, 1000);

 

以上是关于手写防抖、节流 hook(ts版)的主要内容,如果未能解决你的问题,请参考以下文章

手写防抖节流

JS手写面试题 --- 防抖节流

☀️七分钟学会手写防抖和节流

☀️七分钟学会手写防抖和节流

面试官说手写 :防抖和节流

手写防抖节流函数