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);
         }
     }
 }
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章