关于防抖、节流


防抖,节流是前端业务中经常用到的一种优化手段,能极大的节省内存开销和前后端交互次数
我本人防抖用过几次,节流倒是没接触过,于是特地研究了一下,发现这两者其实大同小异;

防抖就是设定一个延迟,在这个延迟时间内如果多次调用,只执行最后一次调用
节流就是设定一个最大时间,在这个时间内管你调用多少次,也只会调用一次,通俗的讲就是采用固定频率

所以这两个本质上没区别,都是为了在多次快速频繁调用时,只调用一次。
不过一个是取最后一次调用,一个是取第一次调用的结果(反正我个人理解是这样😂)

正常业务中,为了适应快速开发,防抖和节流不用自己写,一般用lodash的 debouncethrottle

自己手写的话,可以参考如下代码:

防抖

import React, { useState } from "react";

var init1 = 0;
var timer1 = null; //初始化timer,作为计时清除依据

function App() {
  const [view1, setView1] = useState(null);
  function handleClick1() {
    let res = debounce(
      function () {
        init1++;
        setView1(init1);
      },
      1000,
      false
    );
    res();
  }
  return (
    <div>
      <h2>防抖</h2>
      <button id="btn" onClick={handleClick1}>
        click
      </button>
      <div id="display" style={{ height: 100 }}>
        {view1}
      </div>
    </div>
  );
}

/**
 * 防反跳。fn函数在最后一次调用时刻的delay毫秒之后执行!
 * @param fn 执行函数
 * @param delay 时间间隔
 * @param isImmediate 为true,debounce会在delay时间间隔的开始时立即调用这个函数
 * @returns {Function}
 */
function debounce(fn, delay, isImmediate) {
  console.log("执行");
  return function () {
    var context = this; //获取函数所在作用域this
    var args = arguments; //取得传入参数
    clearTimeout(timer1);
    if (isImmediate && timer1 === null) {
      //时间间隔外立即执行
      fn.apply(context, args);
      timer1 = 0;
      return;
    }
    timer1 = setTimeout(function () {
      fn.apply(context, args);
      timer1 = null;
    }, delay);
  };
}

export default App;

节流

import React, { useState } from "react";

var init2 = 0;
var timer2 = null;
var timeStamp = new Date();

function App() {
  const [view2, setView2] = useState(null);
  function handleClick2() {
    let res = throttle(function () {
      init2++;
      setView2(init2);
    }, 1000);
    res();
  }
  return (
    <div>
      <h2>节流</h2>
      <button id="btn" onClick={handleClick2}>
        click
      </button>
      <div id="display" style={{ height: 100 }}>
        {view2}
      </div>
    </div>
  );
}

function throttle(fn, delay) {
  return function () {
    var context = this; //获取函数所在作用域this
    var args = arguments; //取得传入参数
    if (new Date() - timeStamp > delay) {
      timeStamp = new Date();
      timer2 = setTimeout(function () {
        fn.apply(context, args);
      }, delay);
    }
  };
}

export default App;

React 自定义Hooks 写法

import { useState, useEffect } from "react";
function useDebounce(value: any, delay = 300) {
  const [debouncedValue, setDebouncedValue] = useState(value);
  useEffect(() => {
    const handler = setTimeout(() => {
      setDebouncedValue(value);
    }, delay);
    return () => {
      clearTimeout(handler);
    };
  }, [value, delay]);
  return debouncedValue;
}

export default useDebounce;

效果可查看该视频:


文章作者: Li Dong
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 Li Dong !
评论
  目录