js和React Hooks的防抖和节流

概念
防抖:连续调用后等待一段时间执行一次,如果等待时间内又重新触发,将重新等待一段时间执行
节流:连续调用,在指定时间段内内只执行一次

两者的目的都是减少触发的次数,保证性能和效率,区别在于业务场景和需求的不同。可以触发防抖和节流的事件有:onscroll、onmouseMove、onChange、onResize等。

具体怎么实现的还是看代码比较容易理解

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>防抖:多次调用后只执行一次</title>
</head>
    <body style="height:1400px;">
        <script>
            'use strict'
            function debounce(fn,delay){
                var  timer; //闭包保存局部变量
                return function(...args) {
                    if(timer){
                        clearTimeout(timer)
                    }
                    timer = setTimeout(() => {
                        fn(...args);
                        timer = null;
                    },delay);
                }
            }
            //处理函数
            function mouseMove  (event) {
                let e = event || window.event;
                console.log('移动的位置了:',e.clientX,e.clientY);
            }
            window.onmousemove = debounce(mouseMove,1000);
        </script>
    </body>
</html>

react hooks里的防抖

function useDebounce(fn, delay) {
  const { current } = useRef(null);
  //每次组件重新渲染,都会执行一遍所有的hooks,这样debounce高阶函数里面的timer就不能起到缓存的作用
  //因此需要将定时器绑定到对应的DOM上,防止其他hooks误触发
  return  function (...args) {
    if (current.timer) {
      clearTimeout(current.timer);
    }
    current.timer = setTimeout(fn.apply(this,...args), delay);
  }
}

需要注意的地方:
1.用闭包保存上一次调用的函数
2.闭包里需考虑this的指向和参数传递
3.执行完清除局部变量的引用,杜绝内存泄露

节流有两种处理方法

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>节流:指定时间间隔只执行一次</title>
</head>
<body style="height:1400px;">
    <script>
        'use strict'
        //第一种:用定时器去处理时间间隔
        function throttle(fn,delay){
            let valid = true;
            return function() {
                if(!valid){
                    return false;
                }
                valid = false;
                setTimeout(() => {
                    fn();
                    valid = true;
                }, delay);
            }
        }

        function showTop  () {
            let scrollTop = document.body.scrollTop || document.documentElement.scrollTop;
            console.log('滚动条位置:' + scrollTop);
        }
        window.onscroll = throttle(showTop,1000);


        //第二种:用时间戳去处理时间间隔****************************************************************************************
        function throttle1(fn,delay){
            let startTime = new Date();//使用闭包,变量一直存在内存里
            return function() {
                let endTime = new Date();
                if(endTime - startTime >= delay){
                    fn();
                    startTime = endTime;
                }
            }
        }

        function mouseMove  (event) {
            let e = event || window.event;
            console.log('移动的位置了:',e.clientX,e.clientY);
        }
        window.onmousemove = throttle1(mouseMove,1000)
    </script>
</body>
</html>

react hooks里面的节流

function useThrottle(fn, delay) {
   const { current } = useRef(null);//用于防止其他hook导致的重新渲染
     return function (...args) {
         if (!current.timer) {
            current.timer = setTimeout(() => {
              delete current.timer;
            }, delay);
            fn(...args);
         }
     }
 }
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章